将泛型限制为可以为null的东西 [英] Restricting a generic to things that can be null

查看:1176
本文介绍了将泛型限制为可以为null的东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想限制一个泛型我编码到任何可以是 null 的东西。这基本上是任何类+ System.Nullable (例如 int?等)。



对于类部分来说,它很简单:

  public class MyGeneric< T> T:class {} 

但是,这并不允许我这样做: p>

  var myGeneric = new MyGeneric< int?>(); 

或此:

  var myGeneric = new MyGeneric< Nullable< int>>(); 

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

我尝试使用addind System.Nullable 作为 T 的接受类型:

  public class MyGeneric< T>其中T:class,System.Nullable {} 

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



然后我尝试了

  public class MyGeneric< T>其中T:class,INullable {} 

它可以编译,但是当我这样做时:

  var myGeneric = new MyGeneric< string>(); 

编译器返回这个错误:

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



所以问题是:这是否可能限制一个泛型为任何可以是 null ,以及如何?



作为参考, m使用VS2010 / C#4.0

edit

我被问到我想用它做什么。下面是一个例子:

  namespace Test 
{
public class MyGeneric< T>其中T:class
{
private IEnumerable< T> Vals {get;组; }

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



类程序
{
static void Main(string [] args)
{
MyGeneric< string> ; foo =
MyGeneric< string>(a,b,c,null,null,g);
foo.Print();


$ b code
$ b

这个程序输出<$ c

解决方案

不,没有办法

在编译时执行此操作。



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

  public class MyGeneric< T> 
{
static MyGeneric()
{
var def = default(T);
if(def ValueType& Nullable.GetUnderlyingType(typeof(T))== null)
{
throw new InvalidOperationException(
string.Format(Can not instantiate非空类型:{0},
typeof(T)));
}
}
}


I'd like to restrict a generic I'm coding to anything that can be null. That's basically any class + System.Nullable (e.g. int? and such).

For the class part, it's rather easy:

public class MyGeneric<T> where T : class {}

But then, this doesn't allow me to do this:

var myGeneric = new MyGeneric<int?>();

or this:

var myGeneric = new MyGeneric<Nullable<int>>();

The compiler complains with:
error CS0452: The type 'int?' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test.MyGeneric'

So I tried addind System.Nullable as accepted types for T:

public class MyGeneric<T> where T : class, System.Nullable {}

But it won't do. The compiler returns the following error:
error CS0717: 'System.Nullable': static classes cannot be used as constraints

I then tried

public class MyGeneric<T> where T : class, INullable {}

It does compile, but then when I do:

var myGeneric = new MyGeneric<string>();

The compiler returns this error:
error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test.MyGeneric'. There is no implicit reference conversion from 'string' to 'System.Data.SqlTypes.INullable'.

So, the question is: Is it even possible to restrict a generic to anything that can be null, and of so, how?

For reference, I'm using VS2010 / C# 4.0

edit
I was asked what I want to do with it. Here's an example:

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

This program prints abcg in the debug console.

解决方案

No, there is no way to do this at compile-time.

Personally, I'd just let T be anything, then I'd check its validity in a static constructor:

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

这篇关于将泛型限制为可以为null的东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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