我正在使用反射来遍历一个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
为什么不用反射调用返回默认值(T)的方法?您可以使用任何类型的GetDefault:
public object GetDefault(Type t) { return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null); } public T GetDefaultGeneric() { 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() { // We want an Func which returns the default. // Create that expression here. Expression > e = Expression.Lambda >( // 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
您还应该根据它缓存上述值Type
,但要注意,如果您为大量Type
实例调用此值,并且不要经常使用它,则缓存所消耗的内存可能会超过收益.
为什么你说仿制药不合适?
public static object GetDefault(Type t) { Func
这是优化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 ConcurrentDictionarytypeDefaults = new ConcurrentDictionary (); 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.");
表达式可以在这里提供帮助:
private static DictionarylambdasMap = new Dictionary (); 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(); }
我没有测试这个片段,但我认为它应该为引用类型生成"类型"空值.