574

リフレクションを使用して aTypeのプロパティをループし、特定のタイプをデフォルトに設定しています。ここで、タイプを切り替えてdefault(Type)明示的に設定することもできますが、1 行で行うことをお勧めします。デフォルトに相当するプログラムはありますか?

4

13 に答える 13

778
  • 値型の場合、Activator.CreateInstanceを使用すると正常に動作するはずです。
  • 参照型を使用する場合は null を返すだけです
public static object GetDefault(Type type)
{
   if(type.IsValueType)
   {
      return Activator.CreateInstance(type);
   }
   return null;
}

.net 標準などの新しいバージョンの .net では、次のtype.IsValueTypeように記述する必要があります。type.GetTypeInfo().IsValueType

于 2008-12-09T15:14:35.083 に答える
111

default(T) を返すメソッドをリフレクションで呼び出さないのはなぜですか? 以下の任意のタイプの GetDefault を使用できます。

    public object GetDefault(Type t)
    {
        return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
    }

    public T GetDefaultGeneric<T>()
    {
        return default(T);
    }
于 2011-11-05T19:24:32.780 に答える
95

使用できますPropertyInfo.SetValue(obj, null)。値型で呼び出された場合、デフォルトが提供されます。この動作は、.NET 4.0および.NET 4.5 で文書化されています。

于 2012-04-23T21:48:21.673 に答える
58

.NET 4.0 以降を使用していて、コード外で定義された規則の成文化ではないプログラム バージョンが必要な場合は、 を作成しExpression、コンパイルして、オンザフライで実行できます。

次の拡張メソッドは を受け取り、クラスのメソッドTypeから返された値を取得します。default(T)DefaultExpression

public static T GetDefaultValue<T>()
{
    // We want an Func<T> which returns the default.
    // Create that expression here.
    Expression<Func<T>> e = Expression.Lambda<Func<T>>(
        // The default value, always get what the *code* tells us.
        Expression.Default(typeof(T))
    );

    // Compile and return the value.
    return e.Compile()();
}

public static object GetDefaultValue(this Type type)
{
    // Validate parameters.
    if (type == null) throw new ArgumentNullException("type");

    // We want an Func<object> which returns the default.
    // Create that expression here.
    Expression<Func<object>> e = Expression.Lambda<Func<object>>(
        // Have to convert to object.
        Expression.Convert(
            // The default value, always get what the *code* tells us.
            Expression.Default(type), typeof(object)
        )
    );

    // Compile and return the value.
    return e.Compile()();
}

また、 に基づいて上記の値をキャッシュする必要がありTypeますが、これを多数のTypeインスタンスに対して呼び出しており、常に使用しない場合は、キャッシュによって消費されるメモリが利点を上回る可能性があることに注意してください。

于 2012-10-04T18:24:59.003 に答える
40

なぜジェネリック医薬品は視野外だと言うのですか?

    public static object GetDefault(Type t)
    {
        Func<object> f = GetDefault<object>;
        return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
    }

    private static T GetDefault<T>()
    {
        return default(T);
    }
于 2010-10-26T20:47:47.963 に答える
26

これは、最適化された Flem のソリューションです。

using System.Collections.Concurrent;

namespace System
{
    public static class TypeExtension
    {
        //a thread-safe way to hold default instances created at run-time
        private static ConcurrentDictionary<Type, object> typeDefaults =
           new ConcurrentDictionary<Type, object>();

        public static object GetDefaultValue(this Type type)
        {
            return type.IsValueType
               ? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
               : null;
        }
    }
}
于 2012-11-14T10:00:22.173 に答える
7

選択した答えは良い答えですが、返されるオブジェクトには注意してください。

string test = null;
string test2 = "";
if (test is string)
     Console.WriteLine("This will never be hit.");
if (test2 is string)
     Console.WriteLine("Always hit.");

外挿中...

string test = GetDefault(typeof(string));
if (test is string)
     Console.WriteLine("This will never be hit.");
于 2010-10-16T19:30:22.617 に答える
4

私はこのように同じタスクを実行します。

//in MessageHeader 
   private void SetValuesDefault()
   {
        MessageHeader header = this;             
        Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
   }

//in ObjectPropertyHelper
   public static void SetPropertiesToDefault<T>(T obj) 
   {
            Type objectType = typeof(T);

            System.Reflection.PropertyInfo [] props = objectType.GetProperties();

            foreach (System.Reflection.PropertyInfo property in props)
            {
                if (property.CanWrite)
                {
                    string propertyName = property.Name;
                    Type propertyType = property.PropertyType;

                    object value = TypeHelper.DefaultForType(propertyType);
                    property.SetValue(obj, value, null);
                }
            }
    }

//in TypeHelper
    public static object DefaultForType(Type targetType)
    {
        return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
    }
于 2008-11-28T11:18:09.310 に答える
3

Drorの答えと同等ですが、拡張メソッドとして:

namespace System
{
    public static class TypeExtensions
    {
        public static object Default(this Type type)
        {
            object output = null;

            if (type.IsValueType)
            {
                output = Activator.CreateInstance(type);
            }

            return output;
        }
    }
}
于 2012-06-26T15:48:15.290 に答える
3

式は次の場合に役立ちます。

    private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();

    private object GetTypedNull(Type type)
    {
        Delegate func;
        if (!lambdasMap.TryGetValue(type, out func))
        {
            var body = Expression.Default(type);
            var lambda = Expression.Lambda(body);
            func = lambda.Compile();
            lambdasMap[type] = func;
        }
        return func.DynamicInvoke();
    }

私はこのスニペットをテストしませんでしたが、参照型に対して「型指定された」null を生成する必要があると思います..

于 2011-12-26T00:15:41.180 に答える
0
 /// <summary>
    /// returns the default value of a specified type
    /// </summary>
    /// <param name="type"></param>
    public static object GetDefault(this Type type)
    {
        return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
    }
于 2014-03-31T18:52:11.457 に答える