리플렉션을 사용하여 Type
의 속성 을 반복 하고 특정 유형을 기본값으로 설정합니다. 이제 유형을 전환하고 default(Type)
명시 적으로 설정할 수는 있지만 한 줄로 수행하고 싶습니다. 기본적으로 프로그래밍 방식으로 동등한가?
답변
- 값 유형의 경우 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.");