为什么可能为空&LT ==操作符的工作; T>当没有定义==? [英] Why does the == operator work for Nullable<T> when == is not defined?

查看:170
本文介绍了为什么可能为空&LT ==操作符的工作; T>当没有定义==?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是在看这个答案,其中包含的代码可空< T> 从.NET反射,我注意到两件事情:




  1. 是<$打算时,需要显式转换C $ C>可空< T> 到 T

  2. = = 运营商没有定义



鉴于这两个事实,我很惊讶,这个编译:

 诠释?值= 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:

  1. An explicit conversion is required when going from Nullable<T> to T.
  2. 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, either value is being magically converted to an int (hence allowing int's == operator to be used, or the == operator is being magically defined for Nullable<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, my CustomNullable<T> doesn't work the same way. I am not able to do Assert.IsTrue(value == 10). I get "Operator == cannot be applied to operands of type CustomNullable<int> and int".

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 to null even though Nullable<T> is a struct, but I would expect I should be able to mimic all the other behaviors of Nullable<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.

这篇关于为什么可能为空&LT ==操作符的工作; T&GT;当没有定义==?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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