为什么我可以测试泛型为null时,它可能不可为空或可能不是一个对象?

编程入门 行业动态 更新时间:2024-10-27 12:36:44
本文介绍了为什么我可以测试泛型为null时,它可能不可为空或可能不是一个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

在编写一个包含泛型变量的类时

public class ServiceInvoker< TService> :IDisposable { private TService _Service; public ServiceInvoker() { _Service = Activator.CreateInstance< TService>(); $ b $ public void Invoke(Action< TService> action) { // CAN可以使用null if(_Service == null)抛出新的ObjectDisposedException(ServiceInvoker); .... } public void Dispose() { //不能使用null this._Service = default(TService); $ b我注意到编译器允许我检查null对一个泛型变量,但是,当然,不允许我将它设置为null,因此我们必须使用 default(TService)。

编译器不应该警告我使用null吗?或者是它使用拳击转换为一个对象来做空测试?

我读了关于适用于泛型的空值评估,但我很想知道为什么,而不是如何。

解决方案

为什么我可以测试泛型为null时,它可能不可为空或可能不是对象? / p>

问题不适合;泛型类型的任何表达式的值将始终是运行时的对象或空引用。我想你的意思是:

为什么我可以测试泛型为null,当它的运行时类型可能既不是可空值类型也不是一个引用类型?

C#规范保证了在7.6.10节中对字面null的等同比较是合法的,我在此引用它为了您的方便:

如果将类型参数类型T的操作数与null进行比较,并且T的运行时类型是一个值类型,比较结果为false。 [...]即使T可以表示值类型,也允许 x == null 构造,并且当T是值类型时,结果被简单地定义为false 。

请注意,这里的规格有一个小错误;最后一句应该是非空值类型。

我不确定我是否真的回答了为什么?问题令人满意或不满意。如果这样做不尽如人意,请尝试询问一个更具体的问题。

编译器不应该警告我使用null吗?

没有。为什么您认为编译器应该警告您正确使用该语言的功能?

是否使用装箱转换为对象在此处执行测试?

好的,这有点棘手。一方面,7.6.10节指出:

预定义的引用类型相等运算符从不会导致其操作数发生装箱操作。执行这样的装箱操作是没有意义的,因为对新分配的装箱实例的引用必然与所有其他引用不同。

然而,当我们生成IL来将泛型T与null进行比较时,我们当然确实会生成一个T,一个空载和一个比较。抖动可以足够聪明,以避免实际的拳击内存分配;如果T是一个引用类型,那么它不需要装箱,如果它是一个可为空的值类型,那么它可以变成一个调用来检查HasValue属性,如果它是一个非空值类型,那么拳击和检查可以是变成简单地产生假。我不知道各种不同的jit编译器实现实际上做了什么;如果你有兴趣,请查看!

While writing a class that contains a generic variable

public class ServiceInvoker<TService> : IDisposable { private TService _Service; public ServiceInvoker() { _Service = Activator.CreateInstance<TService>(); } public void Invoke(Action<TService> action) { // CAN use null if (_Service == null) throw new ObjectDisposedException("ServiceInvoker"); .... } public void Dispose() { // CAN'T use null this._Service = default(TService); } }

I noticed that the compiler allows me to check for null on a generic variable, but that, of course, don't allow me to set it to null, hence why we have to use default(TService).

Shouldn't the compiler warn me that I use null? Or is it using boxing conversion to an object to do a test for null here?

I read about the proper null evaluation for generic, but I'm interested in knowing why, instead of just how.

解决方案

Why can I test a generic for null when it may not be nullable or may not be an object?

The question is ill-posed; the value of any expression of generic type will always be either an object or a null reference at runtime. I think you meant to ask:

Why can I test a generic for null when it its runtime type might be neither a nullable value type nor a reference type?

The C# specification guarantees that equality comparison against the literal null is legal in section 7.6.10, which I quote here for your convenience:

If an operand of a type parameter type T is compared to null, and the run-time type of T is a value type, the result of the comparison is false. [...] The x == null construct is permitted even though T could represent a value type, and the result is simply defined to be false when T is a value type.

Note that there is a small error in the spec here; the last sentence should end "non-nullable value type."

I'm never sure if I've actually answered a "why?" question satisfactorily or not. If that's not satisfactory, try asking a more specific question.

Shouldn't the compiler warn me that I use null?

No. Why do you believe that the compiler should warn you for using a feature of the language correctly?

is it using boxing conversion to an object to do a test for null here?

Well, that's a bit of a tricky point. On the one hand, section 7.6.10 states:

The predefined reference type equality operators never cause boxing operations to occur for their operands. It would be meaningless to perform such boxing operations, since references to the newly allocated boxed instances would necessarily differ from all other references.

However, when we generate IL for the comparison of a generic T to null, we of course actually do generate a box of T, a load of null, and a comparison. The jitter can be smart enough to elide the actual memory allocation of the boxing; if T is a reference type then it needs no boxing, if it is a nullable value type then it could be turned into a call to check the HasValue property, and if it is a non-nullable value type then the boxing and check can be turned into simply generating "false". I do not know exactly what the various different jit compiler implementations actually do; if you're interested, check and see!

更多推荐

为什么我可以测试泛型为null时,它可能不可为空或可能不是一个对象?

本文发布于:2023-08-04 03:24:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1292443.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:是一个   能不   为空   或可   对象

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!