为什么我可以测试一个null泛型,当它可能不可为null或可能不是一个对象时?编写包含泛型的类时publicclassServiceInvoker:IDisposable{privateTService_Service;publicServiceInvoker(){_Service=Activator.CreateInstance();}publicvoidInvoke(Actionaction){//可以使用nullif(_Service==null)thrownewObjectDisposedException("ServiceInvoker");....}publicvoidDispose(){//不能使用nullthis._Service=default(TService);我注意到编译器允许我检查泛型变量null,但是,当然,我不允许将它设置为null,所以我们必须使用default(TService)。编译器不应该警告我我正在使用null吗?或者它是否使用装箱来转换为空值测试的对象?我阅读了有关泛型的适当空评估,但我很想知道为什么,而不是如何。当null泛型可能不可为null或可能不是对象时,为什么我可以对其进行测试?问题不合理;泛型类型的任何表达式的值在运行时始终是对象或空引用。我想你想问:当运行时类型既不是可空值类型也不是引用类型时,为什么我可以测试空泛型?C#规范保证在7.6.10节中与文字null的相等比较是合法的,为了方便我在这里引用:如果类型参数类型T的操作数与null进行比较,并且T的运行时类型是值类型,则比较评估为假。[…]即使T可以表示值类型,也允许x==null构造,并且当T是值类型时,结果简单地定义为false。请注意,这里的规范有一个小错误;最后一句应该以“不可空值类型”结尾。我不确定我是否真的回答了“为什么?”问的很满意如果这不令人满意,请尝试提出更具体的问题。编译器不应该警告我我正在使用null吗?不。为什么您认为编译器应该警告您正确使用该语言的功能?它是否使用装箱来转换为空值测试的对象?好吧,这有点棘手。一方面,第7.6.10节指出:预定义的引用类型相等运算符永远不会导致其操作数被装箱。执行这样的装箱操作没有意义,因为对新分配的装箱实例的引用必然不同于所有其他引用。但是当我们生成IL来比较genericT和null时,我们当然实际上为T生成了一个框,一个null的负载和一个比较。抖动可以足够聪明,消除装箱的实际内存分配;如果T是引用类型,则不需要装箱,如果是可空值类型,则可以转为检查HasValue属性的调用,如果是Non-nullable值类型,则装箱和检查可以变成简单的“假”。我不确切知道各种不同的jit编译器实现是做什么的;如果您有兴趣,请查看!CLR知道不可为null的值类型永远不能为null,因此它可能总是返回false。那是你要问的吗?这会编译,但会发出警告:intl=0;if(l==null){//whatever}警告是这样的:warningCS0472:Theresultoftheexpressionisalways'false'sinceavalueoftype'int'isneverequalto'null'oftype'int?'所以它有效,但结果不是很有用。但是,一般来说,这可能是一个有用的测试。为什么你认为编译器应该警告你?当你使用这样的东西时,编译器会警告你:if(1==2)//alwaysfalseif(DogisCat)//nevertrue但在这种情况下,条件可能为真(当TService是refernece类型并且它为null)或false(当它是值类型或引用类型但不为null时)。它完美地代表了if语句的使用(有时为真,有时为假)。以上是C#学习教程:为什么我可以测试一个null泛型,当它可能不可以为空或者可能不是一个对象时?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
