文字列を、ジェネリック戻り値の型のような、int
またはdate
それにlong
基づくジェネリック型に変換したいと思います。
基本的に、Parse<T>(String)
そのような関数はタイプのアイテムを返しますT
。
たとえば、intが渡された場合、関数はint.parse
内部で実行する必要があります。
回答:
あなたの例のように、あなたはすることができます:
int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));
「ジェネリック戻り値の型」の要件を満たすために、独自の拡張メソッドを作成できます。
public static T ChangeType<T>(this object obj)
{
return (T)Convert.ChangeType(obj, typeof(T));
}
これにより、次のことが可能になります。
int i = "123".ChangeType<int>();
IConvertable
必要がある場合は、、T
つまりT ChangeType<T>(this object obj) where T : IConvertable
?も制約するべきではありません。
obj
する必要IConvertible
がありますが、コンパイル時にそれを指定する方法はありません。
このスレッドで答えるには遅すぎるようです。しかし、これが私の実装です:
基本的に、ObjectクラスのExtentionメソッドを作成しました。null許容型、クラス、構造体など、すべての型を処理します。
public static T ConvertTo<T>(this object value)
{
T returnValue;
if (value is T variable)
returnValue = variable;
else
try
{
//Handling Nullable types i.e, int?, double?, bool? .. etc
if (Nullable.GetUnderlyingType(typeof(T)) != null)
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
returnValue = (T) conv.ConvertFrom(value);
}
else
{
returnValue = (T) Convert.ChangeType(value, typeof(T));
}
}
catch (Exception)
{
returnValue = default(T);
}
return returnValue;
}
TypeDescriptor
null許容型とConvert.ChangeType
非null許容型に使用している特定の理由はありますか?このtry
ブロック全体はTypeConverter
2行のコードにしか減らすことができず、null許容と非null許容の両方で機能します。
System.Convert.ChangeType
どのタイプにも変換されません。次のことを考えてください。
これらの変換は、ChangeTypeのこの実装で可能です。
プラネイの答えのよりクリーンなバージョン
public static T ConvertTo<T>(this object value)
{
if (value is T variable) return variable;
try
{
//Handling Nullable types i.e, int?, double?, bool? .. etc
if (Nullable.GetUnderlyingType(typeof(T)) != null)
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
}
return (T)Convert.ChangeType(value, typeof(T));
}
catch (Exception)
{
return default(T);
}
}
.NETには、あるタイプのオブジェクトを別のタイプに変換するための規則がいくつかあります。
ただし、これらの方法は通常よりもはるかに遅く、T.Parse(string)
ボクシングを引き起こし、単一の値を変換するたびに多くの割り当てが必要になります。
以下の場合で、valueString、私は、リフレクションを使用したタイプの、適当な、静的解析方法を見つけ、それを呼び出してラムダ式を構築し、将来の使用のためにコンパイルされたデリゲートを(参照キャッシュするために選んだこの回答例を)。
また、タイプに適切な解析方法がない場合は、上記の方法にフォールバックします(Readmeのパフォーマンスセクションを参照)。
var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.