C# 默认值(类型)的编程等效项

C# 默认值(类型)的编程等效项,c#,reflection,default,C#,Reflection,Default,我使用反射来循环类型的属性,并将某些类型设置为默认类型。现在,我可以在类型上切换并显式设置default(type),但我宁愿在一行中完成。是否有默认的编程等价物?目前还找不到任何简单而优雅的东西,但我有一个想法:如果您知道要设置的属性类型,您可以编写自己的default(t)。有两种情况-T是值类型,T是参考类型。您可以通过选中T.IsValueType来查看这一点。如果T是引用类型,则只需将其设置为null。如果T是一个值类型,那么它将有一个默认的无参数构造函数,您可以调用它来获取一个“空白

我使用反射来循环
类型
的属性,并将某些类型设置为默认类型。现在,我可以在类型上切换并显式设置
default(type)
,但我宁愿在一行中完成。是否有默认的编程等价物?

目前还找不到任何简单而优雅的东西,但我有一个想法:如果您知道要设置的属性类型,您可以编写自己的
default(t)
。有两种情况-
T
是值类型,
T
是参考类型。您可以通过选中
T.IsValueType
来查看这一点。如果
T
是引用类型,则只需将其设置为
null
。如果
T
是一个值类型,那么它将有一个默认的无参数构造函数,您可以调用它来获取一个“空白”值。

我也这样做

//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;
    }
//在MessageHeader中
私有void SetValuesDefault()
{
MessageHeader=this;
Framework.ObjectPropertyHelper.SetPropertiesToDefault(此选项);
}
//在ObjectPropertyHelper中
公共静态void SetPropertiesToDefault(T obj)
{
类型objectType=typeof(T);
System.Reflection.PropertyInfo[]props=objectType.GetProperties();
foreach(道具中的System.Reflection.PropertyInfo属性)
{
if(property.CanWrite)
{
字符串propertyName=property.Name;
类型propertyType=property.propertyType;
对象值=TypeHelper.DefaultForType(propertyType);
SetValue(obj,value,null);
}
}
}
//在TypeHelper中
公共静态对象DefaultForType(类型targetType)
{
返回targetType.IsValueType?Activator.CreateInstance(targetType):null;
}
  • 在使用值类型的情况下,它应该可以正常工作
  • 使用引用类型时,只返回null

在.net的较新版本(如.net standard)中,
type.IsValueType
需要写成
type.GetTypeInfo().IsValueType

选择的答案是一个好答案,但要小心返回的对象

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.");

你为什么说仿制药是不可能的

    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);
    }
publicstaticobjectgetdefault(类型t)
{
Func f=GetDefault;
返回f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null,null);
}
私有静态T GetDefault()
{
返回默认值(T);
}

为什么不调用返回带有反射的默认值(T)的方法?您可以将任何类型的GetDefault用于:

    public object GetDefault(Type t)
    {
        return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
    }

    public T GetDefaultGeneric<T>()
    {
        return default(T);
    }
public对象GetDefault(类型t)
{
返回this.GetType().GetMethod(“GetDefaultGeneric”).MakeGenericMethod(t).Invoke(this,null);
}
公共T GetDefaultGeneric()
{
返回默认值(T);
}

这些表达式在这里有帮助:

    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();
    }
private static Dictionary lambdasMap=new Dictionary();
私有对象GetTypedNull(类型)
{
代表职能;
如果(!lambdasMap.TryGetValue(类型,输出函数))
{
var body=Expression.Default(类型);
var lambda=表达式.lambda(主体);
func=lambda.Compile();
lambdasMap[type]=func;
}
返回函数DynamicInvoke();
}

我没有测试这个代码段,但我认为它应该为引用类型生成“类型化”null。

您可以使用
PropertyInfo.SetValue(obj,null)
。如果对值类型调用,它将为您提供默认值。这种行为被记录并记录下来

相当于Dror的答案,但作为扩展方法:

namespace System
{
    public static class TypeExtensions
    {
        public static object Default(this Type type)
        {
            object output = null;

            if (type.IsValueType)
            {
                output = Activator.CreateInstance(type);
            }

            return output;
        }
    }
}

如果您使用的是.NET 4.0或更高版本,并且您想要的编程版本不是在代码之外定义的规则编码,那么您可以创建、编译并动态运行它

下面的扩展方法将采用a,并通过
表达式
类上的获取返回的值:

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()();
}
publicstatict GetDefaultValue()
{
//我们需要一个返回默认值的Func。
//在这里创建这个表达式。
表达式e=表达式.Lambda(
//默认值,总是得到*代码*告诉我们的。
Expression.Default(typeof(T))
);
//编译并返回值。
返回e.Compile();
}
公共静态对象GetDefaultValue(此类型)
{
//验证参数。
如果(type==null)抛出新的ArgumentNullException(“type”);
//我们需要一个返回默认值的Func。
//在这里创建这个表达式。
表达式e=表达式.Lambda(
//必须转换为对象。
表达式。转换(
//默认值,总是得到*代码*告诉我们的。
Expression.Default(类型)、typeof(对象)
)
);
//编译并返回值。
返回e.Compile();
}

您还应该基于
类型
缓存上述值,但请注意,如果您为大量
类型
实例调用此函数,并且不经常使用它,则缓存消耗的内存可能会超过其好处。

这是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;
        }
    }
}
使用System.Collections.Concurrent;
名称空间系统
{
公共静态类类型扩展
{
//保存运行时创建的默认实例的线程安全方法
私有静态ConcurrentDictionary类型默认值=
新的ConcurrentDictionary();
公共静态对象GetDefaultValue(此类型)
{
返回类型。IsValueType
?typeDefaults.GetOrAdd(类型,Activator.CreateInstance)
:null;
}
}
}
//
///返回指定类型的默认值
/// 
/// 
公共静态对象GetDefault(此类型)
{
返回类型.IsValueType(!type.IsGenericType?激活
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;
        }
    }
}
 /// <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;
    }
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));
}