为什么可能为空< ==操作符的工作; T>当没有定义==? [英] Why does the == operator work for Nullable<T> when == is not defined?
问题描述
我只是在看这个答案,其中包含的代码可空< T>
从.NET反射,我注意到两件事情:
- 是<$打算时,需要显式转换C $ C>可空< T> 到
T
- 的
= =
运营商没有定义
鉴于这两个事实,我很惊讶,这个编译:
诠释?值= 10;
Assert.IsTrue(价值== 10);
通过代码价值== 10
,无论是值
正在神奇地转换为 INT
(因此允许 INT
的 ==
要使用的运营商,或 ==
运营商正在为神奇<$ C定义$ C>可空< INT方式> (或者,我相信不太可能,反射器离开了一些代码)
我会期望有执行下列操作之一:
Assert.IsTrue((value.Equals(10)); //作品因为等于*为*定义
Assert.IsTrue(value.Value == 10); //工作因为==为INT
Assert.IsTrue定义(?(INT)值== 10); //工作,因为的显式转换
当然,这些工作,但 = =
也能工作,这就是我不明白的部分。
我注意到这一点,我问这个问题是我的原因米想写同样有所工程可空℃的结构; T>
。我开始跟上面链接的反射代码,而只是做一些很轻微的修改。不幸的是,我的 CustomNullable< T>
不相同的方式工作。我不能做 Assert.IsTrue(价值== 10)
。我收到操作员 ==
不能应用于类型的操作数 CustomNullable< INT>
和 INT
现在,无论多么微小的修改,我不会期望能够做到......
CustomNullable< T>值= NULL;
......因为我明白,有后方可空<一些编译器魔法; T>
允许的值设置为空
即使可空< T>
是一个结构,但我的会的期望,我应该能够模仿的所有其他行为可空< T>
如果我的代码编写(几乎) 。相同
任何人都可以阐明可空<的各个运营商如何清淡; T>
工作的时候似乎没有他们如何界定?
鉴于这两个事实,我很惊讶,这个编译
块引用>
由于只有这两个事实,这是令人惊讶的。
下面是第三个事实:< STRONG>在C#中,大部分运营商都解禁可空。
通过解禁可空,我的意思是,如果你说:
诠释? X = 1;
诠释? Y = 2;
诠释? Z = X + Y;
那么你得到的:如果x或y为null,则z是空的语义。如果两个不为空再加入他们的价值观,转化为空的,并把结果分配给Z。
这同样适用于平等,但平等是因为在C#有点不可思议,平等仍然是只有两个值。要妥善解除,平等应该是三值:X ==Ÿ应的空的,如果x或y为null,并且真的还是假的,如果X和Y均为非空。这就是它是如何工作在VB,但不是在C#。
我希望我应该能够模仿<$的所有其他行为C $ C>可空< T> 如果我的代码编写(几乎)相同
块引用>
您是将不得不学会与失望,因为住你的期望是完全脱离了现实线。
可空< T>
是一个很特殊的类型并以其神奇的属性是C#语言和运行中的深嵌。例如:
C#自动升降机操作员空。有没有办法说自动升降运营商MyNullable。你可以通过虽然编写您自己的用户定义运算八九不离十
C#有空文字的特殊规则 - 你可以给它们可空变量,并将它们与空的值,而编译器生成这些特殊代码。
nullables的拳击语义深感奇怪,烤成的运行时间。有没有办法模仿他们。
的
是
,为
和凝聚运营商都在对语言出炉。
Nullables不符合
结构
约束。有没有办法模仿的。
等。
I was just looking at this answer, which contains the code for
Nullable<T>
from .NET Reflector, and I noticed two things:
- An explicit conversion is required when going from
Nullable<T>
toT
.- The
==
operator is not defined.Given these two facts, it surprises me that this compiles:
int? value = 10; Assert.IsTrue(value == 10);
With the code
value == 10
, eithervalue
is being magically converted to anint
(hence allowingint
's==
operator to be used, or the==
operator is being magically defined forNullable<int>
. (Or, I presume less likely, Reflector is leaving out some of the code.)I would expect to have to do one of the following:
Assert.IsTrue((value.Equals(10)); // works because Equals *is* defined Assert.IsTrue(value.Value == 10); // works because == is defined for int Assert.IsTrue((int?)value == 10); // works because of the explicit conversion
These of course work, but
==
also works, and that's the part I don't get.The reason I noticed this and am asking this question is that I'm trying to write a struct that works somewhat similarly to
Nullable<T>
. I began with the Reflector code linked above, and just made some very minor modifications. Unfortunately, myCustomNullable<T>
doesn't work the same way. I am not able to doAssert.IsTrue(value == 10)
. I get "Operator==
cannot be applied to operands of typeCustomNullable<int>
andint
".Now, no matter how minor the modification, I would not expect to be able to do...
CustomNullable<T> value = null;
...because I understand that there is some compiler magic behind
Nullable<T>
that allows values to be set tonull
even thoughNullable<T>
is a struct, but I would expect I should be able to mimic all the other behaviors ofNullable<T>
if my code is written (almost) identically.Can anyone shed light on how the various operators of
Nullable<T>
work when they appear not to be defined?解决方案Given these two facts, it surprises me that this compiles
Given only those two facts, that is surprising.
Here's a third fact: in C#, most operators are 'lifted to nullable'.
By "lifted to nullable", I mean that if you say:
int? x = 1; int? y = 2; int? z = x + y;
then you get the semantics of "if either x or y is null then z is null. If both are not null then add their values, convert to nullable, and assign the result to z."
The same goes for equality, though equality is a bit weird because in C#, equality is still only two-valued. To be properly lifted, equality ought to be three-valued: x == y should be null if either x or y is null, and true or false if x and y are both non-null. That's how it works in VB, but not in C#.
I would expect I should be able to mimic all the other behaviors of
Nullable<T>
if my code is written (almost) identically.You are going to have to learn to live with disappointment because your expectation is completely out of line with reality.
Nullable<T>
is a very special type and its magical properties are embedded deeply within the C# language and the runtime. For example:
C# automatically lifts operators to nullable. There's no way to say "automatically lift operators to MyNullable". You can get pretty close by writing your own user-defined operators though.
C# has special rules for null literals -- you can assign them to nullable variables, and compare them to nullable values, and the compiler generates special code for them.
The boxing semantics of nullables are deeply weird and baked into the runtime. There is no way to emulate them.
Nullable semantics for the
is
,as
and coalescing operators are baked in to the language.Nullables do not satisfy the
struct
constraint. There is no way to emulate that.And so on.
这篇关于为什么可能为空< ==操作符的工作; T>当没有定义==?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!