为什么C#&&和|| 运营商的工作方式如何?

这是一个tl;博士

我来自C ++背景。 &&假设检查左侧是否为真,右侧是否为真。 与此有什么关系? 为什么在&&逻辑中使用它?


我无法理解http://msdn.microsoft.com/en-us/library/aa691312%28v=vs.71%29.aspx并提出了一个问题。 我花了很长时间才理解并接受这个答案。 我不得不做很多跟进阅读操作员如何重载真假工作?

操作x && y被评估为T.false(x)? x:T。&(x,y)

为什么它这样做呢? 如果false重载返回true并且true运算符返回true,则根本不计算y。 WTF !!!!

我仍然无法理解。 因为这对我来说太奇怪了,我花了一些时间来理解另一个问题的答案。 在C# v = 1 && 2; 是不行的,你不能做&& on onts。 在C中,这返回true(inheritance人代码/示例http://codepad.org/9iCaqzQ2 )。 如果我们遵循上面的操作规则,我们会这样做

(使用1 && 2)

  • Int.False(1)是错误的
  • 1&2(== 0)
  • Int.True(0)(== false)

这会让你得到错误的结果。

那么…… C#以它的方式执行&&(和||)运算符的原因是什么。

据我所知,你更喜欢a && b定义为((bool)a)&&((bool)b)而不是C#使用的东西。

但我认为引入这种运算符重载是为了支持bool?这样的三态bool?DBBool

让我们为这种类型定义几个例子:

没有短路可能:

 null && true == null null && false == false null || true == true null || false == null 

可以短路:

 false && null == false true || null == true 

这里的基本思想是将null视为未知值,如果结果未确定则返回null,如果结果不改变则返回bool,无论您将什么放入null参数。

现在,您要定义短路逻辑and / or此类型。 如果使用C# truefalse运算符执行此操作,则两者都会在null参数上返回false ,从而获得所需的行为。 有了行为,你就没有。

C#设计者可能并不关心逻辑and / or整数,例如你的例子。 整数不是布尔值,因此不应提供逻辑运算符。 那个bool和整数是同一个东西是c的历史属性之一,新语言不需要镜像。 由于c无法区分布尔和整数,因此int上的按位与逻辑运算符的区别仅存在于c中。 在区分这些类型的语言中,这种区别是不必要的。

在C#中调用&按位操作会产生误导。 && vs &的本质不是逻辑与按位and 。 这不是由您使用的运算符决定的,而是由您使用的类型决定的。 在逻辑类型( boolbool?DBBool )上,两个运算符都是逻辑的,并且在整数类型上是按位而且&&没有意义,因为你不能在整数上短路。 && vs &的本质是第一次短路而第二次没有。

对于完全定义运算符的情况,与c解释一致。 并且由于&&没有在整数上定义,因为对于&& #的C#解释没有意义,因此不存在关于如何对整数求值的问题。

&&被定义为短路运营商; 如果第一个操作数评估为假, 则要求在那里短路而不评估右侧。 你还有什么期望呢? 这允许检查像if(arg != null && arg.Foo) {...}等。

你的问题基本上是说“如果我写了一个错误的操作错误的实现,那么坏事就会发生”……所以; 不要那样做! 要么根本不写真/假操作员,要么就是这样做; 做对了…

还有&| 哪个不短路。

C#比C ++更安全。

首先是&重载,有两个版本,一个是按位AND,它在两个整数类型上运行(例如int,long),并从第一个参数返回AND的结果和第二个参数中的相应位。 例如0011&1010 == 0010。

第二个重载是逻辑AND,它对两个布尔类型(bool)进行操作,当且仅当两个参数都为真时才返回true。

最后你有&&这是条件AND,再次它操作两个布尔类型并且返回true,当且仅当两个参数都为真但它还有添加的保证,如果第一个参数为真,则不会评估第二个参数。 这允许你编写像if(arr!= null && arr.Length> 0)这样的东西……没有短路行为,这会给你一个空引用exception。

|的规则 和|| 是相似的,| 按位和逻辑OR重载,|| 是有条件的OR。

您可能与C ++行为混淆的原因是整数类型在C ++中可隐式转换为bools,0为false且其他任何条件都为真,因此5 && 5在C ++中返回true。 在C#中,intergral类型不能隐式转换为bools,因此5 && 5是类型错误。 &&和|| 然而,在C ++中也是短路的,所以你不应该对C#中的相同内容感到惊讶。

如果将它们转换为VB.Net,这些运算符变得更容易理解,如下所示:

&& = AndAlso:IF foo IsNot Nothing AndAlso foo.bar = 1 then <> …

|| = OrElse:如果foo是Nothing OrElse foo.bar = 0那么…… <> ……

这样,当你用英语阅读它们时,你就会明白他们想要实现的目标。

这里可能忽略的部分问题是为什么C#不会自动将整数转换为布尔值?

自动将int转换为bool(使用C / C ++规则)允许意外分配而不是比较两个值。 C#语言设计师可能想避免这种情况……

 int a, b; if(a == b) { /* They are equal, so execute this code... */ } if(a = b) { /* Were they actually equal? Dunno, but they are now... */ } 

要么

 while(a = b) { /* Eternal loop */ } 

如果你想要评估双方,你需要使用’标准’&和| 运营商。 通常你想要&&和|| 运营商虽然效率高

如果x == false ,则x && y将始终为false – >无需查看y值。 如果x == true ,则x & y发生。 这为您提供了优化的逻辑运算。

对于int ,它将类似于: T.false(x == true) ? x : T.&(x == true, y == true) T.false(x == true) ? x : T.&(x == true, y == true)