リフレクションを使用して aType
のプロパティをループし、特定のタイプをデフォルトに設定しています。ここで、タイプを切り替えてdefault(Type)
明示的に設定することもできますが、1 行で行うことをお勧めします。デフォルトに相当するプログラムはありますか?
13 に答える
- 値型の場合、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
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);
}
使用できますPropertyInfo.SetValue(obj, null)
。値型で呼び出された場合、デフォルトが提供されます。この動作は、.NET 4.0および.NET 4.5 で文書化されています。
.NET 4.0 以降を使用していて、コード外で定義された規則の成文化ではないプログラム バージョンが必要な場合は、 を作成しExpression
、コンパイルして、オンザフライで実行できます。
次の拡張メソッドは を受け取り、クラスのメソッドType
から返された値を取得します。default(T)
Default
Expression
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
インスタンスに対して呼び出しており、常に使用しない場合は、キャッシュによって消費されるメモリが利点を上回る可能性があることに注意してください。
なぜジェネリック医薬品は視野外だと言うのですか?
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);
}
これは、最適化された 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;
}
}
}
選択した答えは良い答えですが、返されるオブジェクトには注意してください。
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.");
私はこのように同じタスクを実行します。
//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;
}
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;
}
}
}
式は次の場合に役立ちます。
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 を生成する必要があると思います..
/// <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;
}