我想要通用的方法返回传递类型的默认值,但是对于集合类型,我想获取空集合而不是null,例如:
GetDefault<int[]>(); // returns empty array of int's GetDefault<int>(); // returns 0 GetDefault<object>(); // returns null GetDefault<IList<object>>(); // returns empty list of objects
我开始写的方法如下:
public static T GetDefault<T>() { var type = typeof(T); if(type.GetInterface("IEnumerable") != null)) { //return empty collection } return default(T); }
如何完成?
编辑:
如果任何人想要获取某些类型的默认值,则基于类型实例而不是类型标识符,可以使用以下结构,即:
typeof(int[]).GetDefault();
内部实现是基于@ 280Z28的答案:
public static class TypeExtensions { public static object GetDefault(this Type t) { var type = typeof(Default<>).MakeGenericType(t); var property = type.GetProperty("Value",BindingFlags.Static | BindingFlags.Public); var getaccessor = property.GetGetMethod(); return getaccessor.Invoke(null,null); } }
解决方法
您可以使用静态构造函数的魔术来高效地执行此操作.要使用代码中的默认值,只需使用Default< T> .Value.在应用期间,该值仅对任何给定类型T一次进行评估.
public static class Default<T> { private static readonly T _value; static Default() { if (typeof(T).IsArray) { if (typeof(T).GetArrayRank() > 1) _value = (T)(object)Array.CreateInstance(typeof(T).GetElementType(),new int[typeof(T).GetArrayRank()]); else _value = (T)(object)Array.CreateInstance(typeof(T).GetElementType(),0); return; } if (typeof(T) == typeof(string)) { // string is IEnumerable<char>,but don't want to treat it like a collection _value = default(T); return; } if (typeof(IEnumerable).IsAssignableFrom(typeof(T))) { // check if an empty array is an instance of T if (typeof(T).IsAssignableFrom(typeof(object[]))) { _value = (T)(object)new object[0]; return; } if (typeof(T).IsGenericType && typeof(T).GetGenericArguments().Length == 1) { Type elementType = typeof(T).GetGenericArguments()[0]; if (typeof(T).IsAssignableFrom(elementType.MakeArrayType())) { _value = (T)(object)Array.CreateInstance(elementType,0); return; } } throw new NotImplementedException("No default value is implemented for type " + typeof(T).FullName); } _value = default(T); } public static T Value { get { return _value; } } }