当前位置: 首页 > 编程语言 > C#

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

时间:2023-04-10 20:11:39 C#

将泛型限制为可以为null的事物这基本上是任何类+System.Nullable(例如int?等)。对于类部分,很简单:publicclassMyGenericwhereT:class{}但是,这不允许我这样做:varmyGeneric=newMyGeneric();或者这样:varmyGeneric=newMyGeneric();编译器抱怨:错误CS0452:类型'int?'必须是引用类型才能将其用作泛型类型或方法'Test.MyGeneric'中的参数'T'所以我尝试将System.Nullable添加为T可接受的类型:publicclassMyGenericwhereT:class,System.Nullable{}但它不会那样做。编译器返回以下错误:ErrorCS0717:'System.Nullable':Astaticclasscannotbeusedasaconstraint然后我尝试了publicclassMyGenericwhereT:class,INullable{}它确实编译了,但是当我这样做时:varmyGeneric=newMyGeneric();编译器返回此错误:错误CS0311:类型“字符串”不能用作泛型类型或方法“Test.MyGeneric”中的类型参数“T”。没有从“字符串”到“System.Data.SqlTypes.INullable”的隐式引用转换。所以,问题是:是否可以将泛型限制为任何可以为null的东西,如何实现?作为参考,我正在使用VS2010/C#4.0编辑我被问到我想用它做什么。这是一个例子:namespaceTest{publicclassMyGenericwhereT:class{privateIEnumerableVals{get;放;}publicMyGeneric(paramsT[]vals){Vals=(IEnumerable)vals;}publicvoidPrint(){foreach(varvinVals.Where(v=>v!=default(T))){Trace.Write(v.ToString());}Trace.WriteLine(string.Empty);}}classProgram{staticvoidMain(string[]args){MyGenericfoo=newMyGeneric("a","b","c",null,null,"g");foo.Print();}}}该程序在调试控制台abcg中打印。不,没有办法在编译时执行此操作。就个人而言,我只是让T成为任何东西,然后我会在静态构造函数中检查有效性:publicclassMyGeneric{staticMyGeneric(){vardef=default(T);if(defisValueType&&Nullable.GetUnderlyingType(typeof(T))==null){thrownewInvalidOperationException(string.Format("无法使用不可为空的类型实例化:{0}",typeof(T)));不,你不能将泛型限制为只能为空的东西。请参阅如何从C#中的泛型方法返回NULL?,例如。唯一提出的解决方案是使用default(T)或使用类限制,因为没有办法限制为只能为null的类型。目前尚不清楚您的目的是什么。更改几行示例代码以使其适用于任何类型,而不仅仅是可为空的类型,所以我不明白你为什么要限制它。此示例也适用于MyGeneric或MyGeneric:usingSystem.Collections.Generic;使用系统诊断;使用System.Linq;namespaceTest{publicclassMyGeneric//删除了“whereT:class”{publicvoidPrint(paramsT[]vals){Print((IEnumerable)vals);}publicvoidPrint(IEnumerablevals){foreach(varvinvals.OfType())//使用“OfType”而不是“Where”{Trace.WriteLine(v.ToString());}Trace.WriteLine(string.Empty);}}classProgram{staticvoidMain(string[]args){MyGenericfoo=newMyGeneric();foo.Print("a","b","c",null,null,"g");}}}从您的示例中不清楚的一件事是,您想使用类级泛型而不是方法级泛型来执行此操作。根据您的示例,您可以执行以下操作:}publicvoidPrint(IEnumerablevals)whereT:class{PrintRestricted(vals.Where(v=>v!=default(T)));}privatevoidPrintRestricted(IEnumerablevals){foreach(varvinvals){Trace.WriteLine(v.ToString());}Trace.WriteLine(string.Empty);}}编写强制限制的包装器方法的代价是相同的功能。有时类型系统根本不能做你想做的事。在这些情况下,您可以更改您想要的内容,也可以解决它。考虑Tuple类的例子。它的“最大”版本看起来像一个元组,其中TRest必须是一个元组。这不是编译时间限制,它严格来说是运行时验证。如果您想在Foo中强制执行T的可空性要求,您可能不得不求助于类似的东西,支持典型的类和可为空的结构。//////Foo类要求T的类型可以为空。例如,一个类或一个Nullable//////classFoo{publicFoo(){if(default(T)!=null)thrownewInvalidOperationException(string.Format("Type{0}isnotvalid",类型(T)));}//这里的其他成员}在这样做的过程中,我记录了该类将要求T与nullable类型兼容,如果不兼容,构造函数将抛出。以上就是C#学习教程:将泛型限制为所有可以为null的东西。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——Foofoo=newFoo();//OKFooworks=newFoo();//也行Foobroken=newFoo();//不行如果转载请注明出处: