C#逻辑顺序和编译器的行为
-
08-06-2019 - |
题
在C#(并随时回答其他语言),有什么了不会的运行时评估的逻辑发言?
例如:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
这份声明并运行时评估第一-
myDt != null
或者:
myDt.Rows.Count > 0
?
有时,编译器会不断评价该声明的倒退?也许时"或"经营人是参与?
&被称为一个合乎逻辑的位操作人员和始终将评估所有的子的表情
什么是一个很好的例子的时候使用这位操作者而不是"短路布尔"?
解决方案
C#:从左到右,处理停止,如果一个非匹配(计算错误)。
其他提示
"C#:从左到右,处理停止,如果有匹配(计算结果为真正的)被发现。"
僵尸羊是错误的,没有足够的代表,以下表决。
问题是有关&&操作者,不||操作员。
在这种情况下的评估将会停止,如果一个虚假的。
在这种情况下的评估将停止,如果一个真正的发现。
我意识到这个问题已经回答了,但我喜欢扔在另一信息是相关的主题。
在语言、C++,在那里实际上,你可以载的行为&&和||经营者,它强烈建议你 不这样做.这是因为当你过载这种行为,最终迫使评价两边的操作。这种做两件事:
- 它打破了懒惰的评价机制,因为过载是一个函数,它必须援用,因此这两个参数进行评估之前的调功能。
- 为评价所述参数并不能保证和可以编译器特有的。因此,目的不会的行为中相同的方式,因为他们在列举的例子,在这个问题/以前的答案。
欲了解更多信息,有一个读的斯科特*梅尔的书, 更有效C++.干杯!
vb.net
if( x isNot Nothing AndAlso x.go()) then
- 评价是左至右
- 为 操作员确保只有在左边,右侧将进行评估(中非常重要,因为ifx什么x。去会崩溃)
你可以使用 和 而不是ofAndAlso在vb。在这种情况下的左侧获得评价第一次作为好,但是正确方面将得到评估,无论结果。
最佳做法:总是使用为,除非你有一个很好的理由为什么不。
它被要求在后续行动为何或何时将任何人使用,而不是为(或&而不是&&): 这里是一个例子:
if ( x.init() And y.init()) then
x.process(y)
end
y.doDance()
在这种情况下,我想init X和Y。Y必须进行初始化了针对y.DoDance能够执行。但是,在初始化()function我这样做也有一些额外的东西喜欢检查一座是开放的,并仅仅如果作出确定, 既, 我应该去做x。处理(y)。
再次,这可能是不必要和不优雅的,在99%的情况下,这就是为什么我说,默认应该使用 为.
@shsteimer
这一概念的谦虚是指的是操作超载。在该声明:...一个是评价第一,如果它评估为假,B永远不会进行评估。这同样适用于
这还不算过载.操作人员超载的术语是指让你定义的行为的运营商,例如*,+,=等。
这会让你写你自己的"Log"类,然后再做
a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.
这样做的
a() || b() // be never runs if a is true
实际上是所谓 短路评估
ZombieSheep是死的。唯一的"疑难杂症",可能会等待的是,这仅仅是如果您使用的是&&操作员。当使用和操作员,这两个表情将评估每一次,无论如何,如果一个或两个估算错误的。
if (amHungry & whiteCastleIsNearby)
{
// The code will check if White Castle is nearby
// even when I am not hungry
}
if (amHungry && whiteCastleIsNearby)
{
// The code will only check if White Castle is nearby
// when I am hungry
}
注意到之间是有区别的&&及&关于如何从你的表情进行评估。
&&被称为短路布尔,并会,正如其他人在这里,停止早期如果结果可以被确定之前,所有的子表达式进行评估。
&被称为一个合乎逻辑的位操作人员和始终将评估所有的子的表达。
作为这样的:
if (a() && b())
只会叫 b 如果 一个 返回 真的.
然而,这样的:
if (a() & b())
总是会叫两个 一个 和 b, 虽然结果的呼叫 一个 是假的,因此称为是 假 无论结果的呼叫 b.
这一同样存在差异的||和|经营者。
一些语文具有有趣的情况下表达执行一个不同的顺序。我特别想着红宝石,但我敢肯定他们借用它来自其他地区(可能Perl).
表达在逻辑将停留左右,但是例如:
puts message unless message.nil?
上述会评估"的信息。nil?"第一,如果它评估为false(除非是喜欢,如果除了它的执行时的条件是虚假的,而不是真正),"把消息"将执行,其印刷品内容的信息可变到屏幕上。
这是一种有趣的方式来结构你的代码有时候...我个人喜欢用它来非常短的1衬如上述。
编辑:
为使这一点更加清晰,以上是相同的:
unless message.nil?
puts message
end
左边,然后停止,如果是空。
编辑:在vb.net 它将评估和可能引发错误的,除非你使用为
这一概念的谦虚是指的是操作超载。在该声明:
if( A && B){
// do something
}
一个是评价第一,如果它评估为假,B永远不会进行评估。这同样适用于
if(A || B){
//do something
}
一个是评价第一,如果它评估为是真的,是从来没有进行评估。
这一概念,负荷超载,适用于(i think)的所有C式语文和许多其他人。
Nopes,至少C#编译器不向后工作(在&&或||).这是左到右。
当事情都是在线进行,他们在执行左到右。
当事情是嵌套的,他们在执行内外。这可能似乎令人困惑,因为通常是什么"最里面的"是在右手边的线路,使它看来似乎是倒着走的...
例如
a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );
事情发生这样的:
- 呼叫
GetAddress
与文字"Orion"
- 呼叫
GetSummary
与文字"Orion"
并的结果GetAddress
- 呼叫
Foo
与文字5
并的结果GetSummary
- 指定这个价值
a
我喜欢猎户座的反应。我只添加两件事情:
- 左边到右仍然适用第一
- 内外以确保所有的争论得到解决之前,呼功能
说我们有以下例子:
a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
GetSummary("Chris", GetAddress("Chris")));
这里是秩序的执行:
GetAddress("Orion")
GetSummary("Orion", ...)
GetAddress("Chris")
GetSummary("Chris", ...)
Foo(...)
- 分配给
a
我不能谈C#'s的法律要求(尽管我做了测试一个类似的例子使用单之前写这篇文章),但是这种秩序保证。
只是为了完整性(因为这是一个语言无关的螺纹也一样),有的语言,如C、C++,那里的秩序是不能保证,除非有一个序列的一点。参考文献: 1, 2.在回答线的问题,但是, &&
和 ||
是序列分在C++(除非过载;也见OJ的极好的回答).因此,一些例子:
foo() && bar()
foo() & bar()
在 &&
种情况下, foo()
保证之前运行 bar()
(如果后者是运行),因为 &&
是一个顺序点。在 &
种情况下,没有这样的保证是由(在C和C++),而事实上 bar()
可以运行之前 foo()
, 或反之亦然。
什么是一个很好的例子的时候使用这位操作者而不是"短路布尔"?
假设你已经标志,说文件的属性。假设你一定义的解读为4,写为2,EXEC为1。在二元,这是:
READ 0100
WRITE 0010
EXEC 0001
每个标志中有一个位置,而且每一个都是独特的。按位经营者让你把这些标志:
flags = READ & EXEC; // value of flags is 0101
我已经听到的地方,编译工作倒退,但是我不确定如何真实。
你使用&当你特别想到评估所有的子的表达,最有可能的,因为他们有副作用,你想要的,即使最后的结果会是 假 因此不执行你的 然后 一部分的你 如果-发言。
注意&和|运作的两位面具和布尔的价值观并不仅仅是为位的操作。他们 叫 按位,但它们定义为两个整数和布尔的数据类型。
它被要求在后续行动为何或何时将任何人使用,而不是为(或&而不是&&):这里是一个例子:
if ( x.init() And y.init()) then x.process(y) end y.doDance()
在这种情况下,我想init X和Y。Y必须进行初始化了针对y.DoDance能够执行。但是,在初始化()function我这样做也有一些额外的东西喜欢检查一座是开放的,并仅仅如果作出确定,对于这两者,我应该去做x。处理(y)。
我相信这是相当令人困惑。尽管你的工作,这不是典型的情况下使用 And
(并且我可能会写这个不同,以使它更清楚). And
(&
在大多数其他语言)是实际上按位与操作。你会用它来计算的位的行动,例如删除标志位或掩蔽和测试的标志:
Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
MsgBox("The text will be set in italic.")
End If