默认(T)与空集,而不是空 [英] default(T) with empty collection instead of null

查看:114
本文介绍了默认(T)与空集,而不是空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想有返回默认值传递类型泛型方法,但对于集合类型我想获得的,而不是空空集,例如:

  GetDefault< INT []>(); //返回廉政局的空数组
GetDefault&其中; INT>(); //返回0
GetDefault&其中;对象>(); //返回null
GetDefault&其中;的IList&其中;对象>>(); //返回对象的空单
 

我开始写的方法如下:

 公共静态牛逼GetDefault< T>()
{
   VAR类型= ty​​peof运算(T);
   如果(type.GetInterface(IEnumerable的)!= NULL))
   {
      //返回空集
   }
   返回默认(T);
}
 

如何完成的呢?

编辑: 如果有人想获得某种类型的默认值的基础上的类型实例的而不是类型标识符的,低于这个结构可以使用,例如:

  typeof运算(INT [])GetDefault()。
 

的实施是内部基于@ 280Z28回答:

 公共静态类TypeExtensions
{
    公共静态对象GetDefault(这个T型)
    {
        VAR类型= ty​​peof运算(默认<>)MakeGenericType(T)。
        VAR属性= type.GetProperty(值,BindingFlags.Static | BindingFlags.Public);
        变种getaccessor ​​= property.GetGetMethod();
        返回getaccessor.Invoke(NULL,NULL);
    }
}
 

解决方案

您可以使用一个静态构造函数的法宝有效地做到这一点。要使用code,其默认值,只需使用默认< T> .value的。该值仅适用于任何类型的评估 T 一旦您的应用程序的时间。

 公共静态类的默认< T>
{
    私人静态只读牛逼_value;

    静态默认()
    {
        如果(typeof运算(T).IsArray)
        {
            如果(typeof运算(T)的.GetArrayRank()→1)
                _value =(T)的(对象)Array.CreateInstance(typeof运算(T)的.GetElementType(),新INT [typeof运算(T)的.GetArrayRank()]);
            其他
                _value =(T)的(对象)Array.CreateInstance(typeof运算(T)的.GetElementType(),0);
            返回;
        }

        如果(typeof运算(T)== typeof运算(字符串))
        {
            // string是IEnumerable的<焦炭>中,但不想把它像一个集合
            _value =默认(T);
            返回;
        }

        如果(typeof运算(IEnumerable的).IsAssignableFrom(typeof运算(T)))
        {
            //检查是否一个空数组是T的实例
            如果(typeof运算(T).IsAssignableFrom(typeof运算(对象[])))
            {
                _value =(T)的(对象)的新对象[0]​​;
                返回;
            }

            如果(typeof运算(T).IsGenericType和放大器;&安培; typeof运算(T).GetGenericArguments()长度== 1)
            {
                键入的ElementType = typeof运算(T)的.GetGenericArguments()[0];
                如果(typeof运算(T).IsAssignableFrom(elementType.MakeArrayType()))
                {
                    _value =(T)的(对象)Array.CreateInstance(的ElementType,0);
                    返回;
                }
            }

            抛出新的NotImplementedException(没有默认值被实现为类型+ typeof运算(T).FullName);
        }

        _value =默认(T);
    }

    公共静态的T值
    {
        得到
        {
            返回_value;
        }
    }
}
 

I'd like to have generic method which returns default value for passed type, but for collection type I'd like to get empty collection instead of null, for example:

GetDefault<int[]>(); // returns empty array of int's
GetDefault<int>(); // returns 0
GetDefault<object>(); // returns null
GetDefault<IList<object>>(); // returns empty list of objects

The method I started to write is following:

public static T GetDefault<T>()
{
   var type = typeof(T);
   if(type.GetInterface("IEnumerable") != null))
   {
      //return empty collection
   }
   return default(T);   
}

How to complete it ?

EDIT: If anyone would like get default value of some type, based on type instance instead of type identifier, this construction below can be used, i.e.:

typeof(int[]).GetDefault();

The implementation is internally based on @280Z28 answer:

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

解决方案

You can use the magic of a static constructor to do this efficiently. To use the default value in code, simply use Default<T>.Value. The value will only be evaluated for any given type T once for the duration of your application.

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

这篇关于默认(T)与空集,而不是空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆