将泛型限制为可以为null的事物

joc*_*oce 23 c# generics null nullable

我想限制一个通用的我编码到任何可能的null.这基本上是任何类+ System.Nullable(例如int?等等).

对于课堂部分,它很容易:

public class MyGeneric<T> where T : class {}
Run Code Online (Sandbox Code Playgroud)

但是,这不允许我这样做:

var myGeneric = new MyGeneric<int?>();
Run Code Online (Sandbox Code Playgroud)

或这个:

var myGeneric = new MyGeneric<Nullable<int>>();
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:
错误CS0452:类型'int?' 必须是引用类型才能在泛型类型或方法'Test.MyGeneric'中将其用作参数'T'

所以我尝试将addind System.Nullable作为可接受的类型T:

public class MyGeneric<T> where T : class, System.Nullable {}
Run Code Online (Sandbox Code Playgroud)

但它不会这样做.编译器返回以下错误:
错误CS0717:'System.Nullable':静态类不能用作约束

然后我试过了

public class MyGeneric<T> where T : class, INullable {}
Run Code Online (Sandbox Code Playgroud)

它确实编译,但是当我这样做时:

var myGeneric = new MyGeneric<string>();
Run Code Online (Sandbox Code Playgroud)

编译器返回此错误:
错误CS0311:类型'string'不能用作泛型类型或方法'Test.MyGeneric'中的类型参数'T'.没有从'string'到'System.Data.SqlTypes.INullable'的隐式引用转换.

所以,问题是:是否有可能将泛型限制为任何可能的null,以及如何?

作为参考,我使用的是VS2010/C#4.0

编辑
我被问到我想用它做什么.这是一个例子:

namespace Test
{
    public class MyGeneric<T> where T : class
    {
        private IEnumerable<T> Vals { get; set; }

        public MyGeneric(params T[] vals)
        {
            Vals = (IEnumerable<T>)vals;
        }

        public void Print()
        {
            foreach (var v in Vals.Where(v => v != default(T)))
            {
                Trace.Write(v.ToString());
            }
            Trace.WriteLine(string.Empty);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyGeneric<string> foo = 
                new MyGeneric<string>("a", "b", "c", null, null, "g");
            foo.Print();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序abcg在调试控制台中打印.

Meh*_*dad 12

不,在编译时没有办法做到这一点.

就个人而言,我只是让T任何东西,然后我会在静态构造函数中检查它的有效性:

public class MyGeneric<T>
{
    static MyGeneric()
    {
        var def = default(T); 
        if (def is ValueType && Nullable.GetUnderlyingType(typeof(T)) == null)
        {
            throw new InvalidOperationException(
                string.Format("Cannot instantiate with non-nullable type: {0}",
                    typeof(T)));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 假设你恰当地记录了`T`必须可以为空的事实,并且鉴于在编译时没有办法强迫它,那么我不明白为什么这是不好的做法.为什么调试难?在调用任何方法之前,只要使用类*就会抛出它.我的意思是,我很乐意告诉你是否有更好的方法,但是在编译时根本没办法做到这一点,而且除了静态构造函数之外,我没有看到如何检查它. (3认同)