web-dev-qa-db-ja.com

タイプがSystem.Typeとしてのみ知られている場合、タイプのデフォルト値を取得する方法は?

特定の型のデフォルト値を返すメソッドが必要で、そのメソッドが汎用である場合は、次のようにデフォルト値を返すことができます。

public static T GetDefaultValue()
{
  return default(T);
}

タイプがSystem.Typeオブジェクトのみの場合、同様のことを行うことはできますか?

public static object GetDefaultValue(Type type)
{
  //???
}
40
Patrick Klug

実際には値型についてのみ心配する必要があるため(参照型はnullになります)、Activator.CreateInstanceを使用してそれらのデフォルトコンストラクターを呼び出すことができます。

public static object GetDefaultValue(Type type) {
   return type.IsValueType ? Activator.CreateInstance(type) : null;
}

編集:ジョンは(もちろん)正しいです。 IsClassは十分に網羅的ではありません-Falseがインターフェースの場合、typeを返します。

70
Mark Brackett

これが私が通常行う方法です。これにより、「IsValueType」全体やコンストラクターの検索の問題を完全に回避できます。

public static object MakeDefault(this Type type)
{
    var makeDefault = typeof(ExtReflection).GetMethod("MakeDefaultGeneric");
    var typed = makeDefault.MakeGenericMethod(type);
    return typed.Invoke(null, new object[] { });
}

public static T MakeDefaultGeneric<T>()
{
    return default(T);
}
7
jonfuller

ジェネリックがないと、型にパラメーターのないコンストラクターがあることを保証できませんが、リフレクションを使用してコンストラクターを検索できます。

public static object GetDefaultValue(Type type)
{
    ConstructorInfo ci = type.GetConstructor( new Type[] {} );
    return ci.Invoke( new object[] {} );
}

コンソールアプリでこれを試しましたが、クラスの「デフォルト」インスタンスが返されます—クラスであると想定しています。参照型でも機能する必要がある場合は、追加の手法が必要になります。

1
harpo