回答:
public static object GetDefault(Type type)
{
if(type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
.net標準などの.netの新しいバージョンでtype.IsValueType
は、次のように記述する必要があります。type.GetTypeInfo().IsValueType
default(T) != (T)(object)default(T) && !(default(T) != default(T))
、同等であるため、それがボックス化されているかどうかは関係ありません。
default(T) != default(T)
ことです... false を返す可能性があり、それは不正行為です!=)
Array.CreateInstance(type, length)
。
リフレクションを使用して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);
}
nameof(GetDefaultGeneric)
代わりにできる限り使用する"GetDefaultGeneric"
.NET 4.0以降を使用していて、コードの外部で定義されたルールの体系化されていないプログラムバージョンが必要な場合は、を作成Expression
、コンパイルして、その場で実行できます。
次の拡張メソッドはa 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
インスタンスに対して呼び出す場合は、常に使用しないでください。キャッシュによって消費されるメモリがメリットを上回る可能性があります。
e.Compile()
。それが表現のポイントです。
e.Compile()
キャッシュされるべきですが、と仮定すると、このメソッドは、例えばの場合、およそ14倍高速ですlong
。ベンチマークと結果については、gist.github.com / pvginkel / fed5c8512b9dfefc2870c6853bbfbf8bをご覧ください。
e.Compile()
のに、なぜキャッシュではなくe.Compile()()
ですか?つまり、型のデフォルト型は実行時に変更できますか?そうでない場合(私はそうだと思います)、コンパイルされた式ではなく、結果をキャッシュに格納するだけで、パフォーマンスがさらに向上します。
ジェネリック医薬品が視野に入らないのはなぜですか?
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);
}
これは、最適化されたフレムのソリューションです。
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;
}
}
}
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.");
式はここで役立ちます:
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を生成する必要があると思います。
"typed" nulls
-説明してください。どのオブジェクトを返しますか?タイプのオブジェクトを返し、type
その値がnull
である場合、そのオブジェクトはそれ以外の情報を持つことはできませんnull
。null
値をクエリして、その型が何であるかを調べることはできません。nullを返さないが..を返す場合..わからない場合は、のようには動作しませんnull
。
私はこのように同じ仕事をします。
//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;
}
@Rob Fonseca-Ensorのソリューションに対するわずかな調整:GetMethodではなくGetRuntimeMethodを使用しているため、次の拡張メソッドも.Net Standardで機能します。
public static class TypeExtensions
{
public static object GetDefault(this Type t)
{
var defaultValue = typeof(TypeExtensions)
.GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
.MakeGenericMethod(t).Invoke(null, null);
return defaultValue;
}
public static T GetDefaultGeneric<T>()
{
return default(T);
}
}
...そして品質を気にする人のための対応する単体テスト:
[Fact]
public void GetDefaultTest()
{
// Arrange
var type = typeof(DateTime);
// Act
var defaultValue = type.GetDefault();
// Assert
defaultValue.Should().Be(default(DateTime));
}
/// <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;
}
Nullable<T>
型に対しては機能しません。default(Nullable<T>)
これは、に相当するものを返しませんnull
。Drorが認めた回答はより効果的に機能します。