답변:
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)
반환을 거짓으로 만들 수 있습니다 . =)
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"
사용할 수 있습니다 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
인스턴스에 대해이 값을 호출 하고 지속적으로 사용하지 않는 경우 캐시에서 사용하는 메모리가 이점을 능가 할 수 있습니다.
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);
}
이것은 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;
}
}
}
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();
}
이 스 니펫을 테스트하지는 않았지만 참조 유형에 대해 "typed"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의 승인 된 답변이 더 잘 작동합니다.