清楚,外行人对于|的区别的解释 和|| 在C#?

好吧,我已经阅读过很多次了,但是我还没有听清楚,容易理解(和令人难忘)的方法来了解它们之间的区别:

if (x | y) 

 if (x || y) 

在C#的上下文中 任何人都可以帮助我学习这个基本事实,以及C#如何特别对待它们(因为它们似乎做同样的事情)。 如果给定的一段代码之间的差异是无关紧要的,那么我应该将其默认为最佳实践?

||逻辑运算符还是运算符。 看到这里 。 如果至less有一个操作数是真的,则它的计算结果为真。 您只能使用它与布尔操作数; 在整数操作数中使用它是错误的。

 // Example var one = true || bar(); // result is true; bar() is never called var two = true | bar(); // result is true; bar() is always called 

|运营商。 看到这里 。 如果应用于布尔types,则至less有一个操作数为真时,计算结果为true。 如果应用于整数types,则评估为另一个数字。 如果至less有一个操作数设置了相应的位,则该数字的每个位均设置为1。

 // Example var a = 0x10; var b = 0x01; var c = a | b; // 0x11 == 17 var d = a || b; // Compile error; can't apply || to integers var e = 0x11 == c; // True 

对于布尔操作数, a || b a || b a | b 相同 a | b ,只有一个例外,如果a是真的,则不评估b 。 为此, || 据说是“短路”。

如果给定的一段代码之间的差异是无关紧要的,那么我应该将其默认为最佳实践?

如前所述,这种差异并不是无关紧要的,所以这个问题部分是没有意义的。 至于“最佳做法”,没有一个:只要使用哪一个操作者是正确的就可以使用。 一般来说,人们赞成||| 因为你可以肯定它不会产生不必要的副作用。

与布尔操作数一起使用时 运算符就像||一样是一个逻辑运算符 ,但区别在于|| 运营商做短路评估和| 运营商没有。

这意味着第二个操作数总是使用|来评估 运算符,但使用|| 运算符第二个操作数仅在第一个操作数计算结果为false时才被计算。

expression式的结果对于两个操作符总是相同的,但是如果第二个操作数的求值导致别的东西改变,那么只有在使用| 运营商。

例:

 int a = 0; int b = 0; bool x = (a == 0 || ++b != 0); // here b is still 0, as the "++b != 0" operand was not evaluated bool y = (a == 0 | ++b != 0); // here b is 1, as the "++b != 0" operand was evaluated. 

||的短路评估 运算符可用于编写较短的代码,因为如果第一个操作数为true,则仅评估第二个操作数。 而不是写这样的:

 if (str == null) { Console.WriteLine("String has to be at least three characters."); } else { if (str.Length < 3) { Console.WriteLine("String has to be at least three characters."); } else{ Console.WriteLine(str); } } 

你可以这样写:

 if (str == null || str.Length < 3) { Console.WriteLine("String has to be at least three characters."); } else{ Console.WriteLine(str); } 

第二个操作数仅在第一个操作数为假时才被计算,因此您知道可以安全地在第二个操作数中使用该string引用,因为如果计算第二个操作数,则不能为空。

在大多数情况下,你会想要使用|| 运算符而不是| 运营商。 如果第一个操作数为假,则不需要评估第二个操作数就可以得到结果。 此外,很多人(显然)不知道你可以使用| 运算符与布尔操作数,所以他们会看到它在代码中使用这种方式感到困惑。

他们不一样。 一个是按位OR,另一个是逻辑OR。

X || Y是逻辑或,与“X或Y”相同,适用于bool值。 它用于条件或testing。 在这种情况下,X和Y可以用任何expression式来代替, 例:

 if (File.Exists("List.txt") || x > y ) { ..} 

如果两个条件中的任何一个为真,则该条款评估为真。 如果第一个条件为真(如果文件存在),则第二个条件不需要也不会被评估。

单pipe(|)是一个按位或。 要知道这意味着您必须了解数字如何存储在计算机中。 假设你有一个16位的数量(Int16),其值为15,实际上存储为0x000F(hex),与二进制的0000 0000 0000 1111相同。 按位OR将两个量和OR的每一对相应位组合在一起,因此,如果任一数量中的位为1,则结果中为1。 因此,如果a = 0101 0101 0101 0101(以hex计算为0x5555)和b = 1010 1010 1010 1010(即0xAAAA),则a | b = 1111 1111 1111 1111 = 0xFFFF。

您可以在C#中使用按位OR(单个pipe道)来testing是否打开了一个或多个特定位。 如果你有,我们可以这样做,12个布尔值或二进制值来testing,而且它们都是独立的。 假设你有一个学生数据库。 一组独立的布尔值可能是像男性/女性,家庭/校园,当前/未当前,已注册/未注册等等。而不是为每个值存储布尔字段,您可以存储只是每一个单一的位。 男/女可能位1.登记/不可能位2。

那么你可以使用

  if ((bitfield | 0x0001) == 0x0001) { ... } 

作为一个testing,看看是否没有打开位,除了“学生是男性”位,这是忽略。 咦? 那么,按位OR将为每个数字中的每个位返回1。 如果按位OR = 0x0001的结果,意味着在位域中没有位被打开,除了第一位(0x0001)外,但是不能确定第一位是否打开,因为它被掩盖。

有一个相应的&&和&,这是逻辑AND和按位AND。 他们有类似的行为。

您可以使用

  if ((bitfield & 0x0001) == 0x0001) { ... } 

查看是否在位域中打开了第一位。

编辑:我不能相信我被拒绝了!

好的答案,但是让我加上||的右边expression式 如果左侧expression式为true则不进行评估。 考虑到评估条件为a)性能密集型或b)产生副作用(罕见)的情况,请记住这一点。

与目前为止大部分答案不同的是,C ++中的含义并不完全相同。

对于任何两个expression式A和B来评估布尔值,A || B和A | B做几乎相同的事情。

A | B评估A和B,如果其中一个评估为真,结果是真实的。

A || B做几乎相同的事情,除了首先评估A,然后只评估B是否必要。 由于如果A或B为真,则整个expression式为真,如果A为真,则根本不需要testingB. 所以|| 短路,并在可能的情况下跳过评估第二个操作数,其中| 运营商将始终评估两者。

| 运营商不常使用,往往不会有所作为。 我能想到的唯一常见的情况是:

 if ( foo != null || foo.DoStuff()){ // assuming DoStuff() returns a bool } 

这是有效的,因为如果左testing失败,DoStuff()成员函数永远不会被调用。 也就是说,如果foo为null,我们不会在其上调用DoStuff。 (这会给我们一个NullReferenceException)。

如果我们使用了| 运算符DoStuff()将被调用,而不pipefoo是否为null。

在整数上,只有| 运算符被定义,并且是一个按位“或”,正如其他答案所描述的那样。 || 运算符虽然没有为整数types定义,但很难将它们混合到C#中。

| 是一个按位或运算符(数字,整数)。 它的工作原理是将数字转换为二进制,并对每个相应的数字进行“或”运算。 那么数字在计算机中已经以二进制表示,因此在运行时不会发生这种转换;)

|| 是一个逻辑OR运算符(布尔)。 它只适用于真值和假值。

下面的代码可以在C / C ++中使用,因为它没有对布尔types的第一类支持,它将每个expression式都用“on”位作为真,否则为false。 事实上,如果x和y是数字types,下面的代码在C#或Java中将不起作用。

 if (x | y) 

所以上面代码的显式版本是:

 if ( (x | y) != 0) 

在C中,任何expression式都会有一个“On”位,结果为true

int i = 8;

如果(i)//在C中有效,结果为true

int joy = -10;

如果(喜悦)//在v的vaild结果为真

现在回到C#

如果x和y是数字types,您的代码: if(x | y)将不起作用。 你有没有试过编译它? 不起作用

但是,对于你的代码,我可以假设x和y是布尔types,所以它会工作,所以| |之间的区别 和|| 对于布尔types,|| 是短路的,| 不是。 以下内容的输出:

  static void Main() { if (x | y) Console.WriteLine("Get"); Console.WriteLine("Yes"); if (x || y) Console.WriteLine("Back"); Console.ReadLine(); } static bool x { get { Console.Write("Hey"); return true; } } static bool y { get { Console.Write("Jude"); return false; } } 

是:

 HeyJudeGet Yes HeyBack 

裘德不会被打印两次,|| 是一个布尔运算符,许多C语言派生语言布尔运算符被短路 ,布尔expression式如果被短路则性能更高。

至于外行的话,当你说短路的时候,例如|| (或运算符),如果第一个expression式已经为true,则不需要评估第二个expression式。 例如:if(answer =='y'|| answer =='Y'),如果用户按小y,程序不需要评估第二个expression式(答案=='Y')。 这是短路。

在我上面的示例代码中,X是真实的,所以||在||上 运营商将不会被进一步评估,因此没有第二个“裘德”输出。

即使X和Y是布尔types,也不要在C#中使用这种types的代码: if(x | y) 。 不performance。

第一个按位运算符在两个数值上工作,结果在第三个数值上。

如果你有二进制variables

 a = 0001001b; b = 1000010b; 

然后

 a | b == 1001011b; 

也就是说,如果两个操作数中的任何一个都是1,那么结果中有一位是1。 (为了清晰起见,我的示例使用了8位数字)

“double pipe”||是一个逻辑OR运算符,它接受两个布尔值并导致第三个结果。

不以任何方式,形状或forms深入细节,这是一个真正的外行人的版本。

想想“|” 直译为“或”英文; 想到“||” as“or else”in English。

同样用“&”作为英文的“and”; 把“&&”想成“也是”用英文。

如果你使用这些术语来为自己阅读一个expression,他们通常会更有意义。

强烈build议阅读本文从Dotnet Mob

对于OR逻辑操作,如果其操作数的任何一个被评估为真,则整个expression式评估为真

这是什么|| 运营商会 – 当它发现真的时候,它会跳过剩下的评估。 而| 运算符评估它的完整操作数来评估整个expression式的值。

 if(true||Condition1())//it skip Condition1()'s evaluation { //code inside will be executed } if(true|Condition1())//evaluates Condition1(), but actually no need for that { //code inside will be executed } 

不pipe是OR(||)还是AND(&&)运算符,最好使用逻辑运算符的短路循环版本。


考虑下面的代码片段

 int i=0; if(false||(++i<10))//Now i=1 { //Some Operations } if(true||(++i<10))//i remains same, ie 1 {} 

这种效应被称为副作用 ,实际上在短路逻辑运算符的expression式的右侧出现

参考: C#中的短路评估

虽然它已经被正确地回答了,我想我会添加一个真正的外行人的答案,因为很多时候,这是我在这个网站上的感觉:)。 另外我会加上&vs. &&的例子,因为它是相同的概念

| vs ||

基本上你倾向于使用|| 当你只想评估第二部分如果第一部分它是假的。 所以这:

 if (func1() || func2()) {func3();} 

是相同的

 if (func1()) { func3(); } else { if (func2()) {func3();} } 

这可能是一种节省处理时间的方法。 如果func2()花了很长时间来处理,如果func1()已经是真的,你不会想这样做。

&vs &&

在&与&&&的情况下,如果第一部分是TRUE,那么您只评估第二部分。 比如这个:

 if (func1() && func2()) {func3();} 

是相同的

 if (func1()) { if (func2()) {func3();}} } 

这可能是必要的,因为func2()可能取决于func1()首先是真的。 如果你使用&和func1()求值为false,那么会运行func2(),这可能会导致运行时错误。

杰夫的外行人

我有这个相同的问题,但我没有完全理解的答案,直到我发现这个网页,解释一切很好,并提供了很好的例子: http : //www.codeproject.com/Articles/544990/Understand-how-bitwise -operators工作-Csharp的和-V