C# default(Type) 的编程等效项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/325426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:16:30  来源:igfitidea点击:

Programmatic equivalent of default(Type)

c#reflectiondefault

提问by tags2k

I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type)explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?

我正在使用反射来遍历 aType的属性并将某些类型设置为其默认值。现在,我可以在类型上进行切换并default(Type)明确设置,但我宁愿在一行中进行。是否有默认的编程等价物?

采纳答案by Dror Helper

  • 如果是值类型,请使用Activator.CreateInstance,它应该可以正常工作。
  • 使用引用类型时只返回 null
public static object GetDefault(Type type)
{
   if(type.IsValueType)
   {
      return Activator.CreateInstance(type);
   }
   return null;
}

In the newer version of .net such as .net standard, type.IsValueTypeneeds to be written as type.GetTypeInfo().IsValueType

在.net标准等较新版本的.net中,type.IsValueType需要写成type.GetTypeInfo().IsValueType

回答by Vilx-

Can't find anything simple and elegant just yet, but I have one idea: If you know the type of the property you wish to set, you can write your own default(T). There are two cases - Tis a value type, and Tis a reference type. You can see this by checking T.IsValueType. If Tis a reference type, then you can simply set it to null. If Tis a value type, then it will have a default parameterless constructor that you can call to get a "blank" value.

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

回答by kpollock

I do the same task like this.

我做同样的任务。

//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;
    }

回答by BSick7

The chosen answer is a good answer, but be careful with the object returned.

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

string test = null;
string test2 = "";
if (test is string)
     Console.WriteLine("This will never be hit.");
if (test2 is string)
     Console.WriteLine("Always hit.");

Extrapolating...

推断...

string test = GetDefault(typeof(string));
if (test is string)
     Console.WriteLine("This will never be hit.");

回答by Rob Fonseca-Ensor

Why do you say generics are out of the picture?

你为什么说泛型不在图片中?

    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);
    }

回答by drake7707

Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:

为什么不使用反射调用返回 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);
    }

回答by Konstantin Isaev

The Expressions can help here:

表达式可以在这里提供帮助:

    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();
    }

I did not test this snippet, but i think it should produce "typed" nulls for reference types..

我没有测试这个片段,但我认为它应该为引用类型产生“类型化”的空值..

回答by JoelFan

You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0and in .NET 4.5.

您可以使用PropertyInfo.SetValue(obj, null). 如果在值类型上调用,它将为您提供默认值。此行为记录在 .NET 4.0.NET 4.5 中

回答by Paul Fleming

Equivalent to Dror's answer but as an extension method:

相当于 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;
        }
    }
}

回答by casperOne

If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.

如果您使用的是 .NET 4.0 或更高版本,并且您想要一个不是代码之外定义的规则的编纂的编程版本,您可以创建一个Expression,即时编译和运行它。

The following extension method will take a Typeand get the value returned from default(T)through the Defaultmethodon the Expressionclass:

以下扩展方法将采用 aTypedefault(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()();
}

You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Typeinstances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.

您还应该根据 缓存上述值Type,但请注意,如果您为大量Type实例调用它,并且不要经常使用它,缓存消耗的内存可能会超过好处。