对 | 之间差异的清晰、通俗易懂的解释 和|| 在 c# 中?

发布于 2024-07-15 11:56:22 字数 252 浏览 12 评论 0原文

好吧,我已经读过很多次了,但我还没有听到一种清晰、易于理解(且令人难忘)的方法来学习

if (x | y)

:和

if (x || y)

C# 上下文中的 .. 之间的区别。 谁能帮助我了解这个基本事实,以及 C# 具体如何以不同的方式对待它们(因为它们似乎做同样的事情)。 如果给定代码段之间的差异无关紧要,那么我应该默认采用哪一个作为最佳实践?

Ok, so I've read about this a number of times, but I'm yet to hear a clear, easy to understand (and memorable) way to learn the difference between:

if (x | y)

and

if (x || y)

..within the context of C#. Can anyone please help me learn this basic truth, and how C# specifically, treats them differently (because they seem to do the same thing). If the difference a given piece of code has between them is irrelevant, which should I default to as a best-practise?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

救赎№ 2024-07-22 11:56:22

||逻辑或 运算符。 请参阅此处。 如果至少有一个操作数为 true,则其计算结果为 true。 您只能将它与布尔操作数一起使用; 将它与整数操作数一起使用是错误的。

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

| 运算符。 请参阅此处。 如果应用于布尔类型,如果至少有一个操作数为 true,则其计算结果为 true。 如果应用于整数类型,它将计算为另一个数字。 如果至少一个操作数具有相应的位设置,则该数字的每个位都设置为 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 || ba | 相同 b,唯一的例外是,如果 a 为 true,则不会评估 b。 因此,|| 被称为“短路”。

如果给定代码段之间的差异无关紧要,我应该默认采用哪一个作为最佳实践?

如前所述,差异并非无关紧要,因此这个问题部分没有实际意义。 至于“最佳实践”,没有一个:您只需使用正确的运算符即可。 一般来说,人们更喜欢 || 而不是 | 作为布尔操作数,因为你可以确定它不会产生不必要的副作用。

|| is the logical-or operator. See here. It evaluates to true if at least one of the operands is true. You can only use it with boolean operands; it is an error to use it with integer operands.

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

| is the or operator. See here. If applied to boolean types, it evaluates to true if at least one of the operands is true. If applied to integer types, it evaluates to another number. This number has each of its bits set to 1 if at least one of the operands has a corresponding bit set.

// 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

For boolean operands, a || b is identical to a | b, with the single exception that b is not evaluated if a is true. For this reason, || is said to be "short-circuiting".

If the difference a given piece of code has between them is irrelevant, which should I default to as a best-practise?

As noted, the difference isn't irrelevant, so this question is partially moot. As for a "best practice", there isn't one: you simply use whichever operator is the correct one to use. In general, people favor || over | for boolean operands since you can be sure it won't produce unnecessary side effects.

箜明 2024-07-22 11:56:22

当与布尔操作数一起使用时,| 运算符与 || 一样是逻辑运算符,但不同之处在于 || 运算符会短路求值,而 | 运算符则不然。

这意味着始终使用 | 运算符计算第二个操作数,但使用 || 运算符,仅当第一个操作数计算结果为 false 时才计算第二个操作数。

两个运算符的表达式结果始终相同,但如果第二个操作数的求值导致其他内容发生更改,则只有使用 | 运算符才能保证发生这种情况。

示例:

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);
}

仅当第一个操作数为 false 时才计算第二个操作数,因此您知道可以安全地在第二个操作数中使用字符串引用,因为如果第二个操作数为评价。

在大多数情况下,您需要使用 || 运算符而不是 | 运算符。 如果第一个操作数为假,则无需计算第二个操作数即可获得结果。 另外,很多人(显然)不知道可以将 | 运算符与布尔操作数一起使用,因此当他们在代码中看到这种用法时,他们会感到困惑。

When used with boolean operands the | operator is a logical operator just as ||, but the difference is that the || operator does short circuit evaluation and the | operator does not.

This means that the second operand is always evaluated using the | operator, but using the || operator the second operand is only evaluated if the first operand evaluates to false.

The result of the expression is always the same for both operatrors, but if the evaluation of the second operand causes something else to change, that is only guaranteed to happen if you use the | operator.

Example:

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.

The short-circuit evaluation of the || operator can be used to write shorter code, as the second operand only is evaluated if the first operand is true. Instead of writing like this:

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);
   }
}

You can write like this:

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

The second operand is only evaluated if the first is false, so you know that you can safely use the string reference in the second operand as it can not be null if the second operand is evaluated.

In most cases you would want to use the || operator rather than the | operator. If the first operand is false, there is no need to evaluate the second operand to get the result. Also, a lot of people (evidently) doesn't know that you can use the | operator with boolean operands, so they would get confused when seeing it used that way in the code.

优雅的叶子 2024-07-22 11:56:22

他们不一样。 一种是按位或,一种是逻辑或。

X|| Y 是逻辑或,与“X 或 Y”含义相同,适用于布尔值。 它用于条件或测试。 在这种情况下,X 和 Y 可以替换为任何计算结果为布尔值的表达式。 示例:

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

如果两个条件之一为 true,则该子句的计算结果为 true。 如果第一个条件为真(如果文件存在),则不需要也不会评估第二个条件。

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

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

然后您可以用作

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

测试来查看是否没有打开任何位,除了“学生是男性”位之外,该位被忽略。 啊? 那么,按位或会为任一数字中打开的每一位返回 1。 如果上面按位或的结果= 0x0001,则意味着位域中没有打开的位,除了第一位(0x0001)之外,但您无法确定第一个位是否打开位打开,因为它被屏蔽了。

对应的还有&& 和&,即逻辑与和按位与。 他们有类似的行为。

您可以使用它

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

来查看位字段中的第一位是否打开。

编辑:我不敢相信我因此被否决了!

They are not the same. One is bitwise OR and one is logical OR.

X || Y , is a logical or, means the same as "X or Y" and applies to bool values. It is used in conditionals or tests. X and Y in that case can be replaced with any expression that evaluates to a bool. Example:

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

The clause evaluates to true if either of the two conditions is true. If the first condition is true (if the file exists), then the second condition need not and will not be evaluated.

The single pipe ( | ) is a bitwise OR. To know what this means you must be understand how numbers are stored in the computer. Suppose you have a 16-bit quantity (Int16) that holds the value 15. It is actually stored as 0x000F (in hex) which is the same as 0000 0000 0000 1111 in binary. The bitwise OR takes two quantities and OR's each pair of corresponding bits together, so that if the bit is 1 in either quantity, it is 1 in the result. Therefore, if a = 0101 0101 0101 0101 (which evaluates to 0x5555 in hex) and b = 1010 1010 1010 1010 (which is 0xAAAA), then a | b = 1111 1111 1111 1111 = 0xFFFF.

You can use bitwise OR's (single pipe) in C# to test if one or more of a particular set of bits is turned on. You might do this if you have, let's say, 12 booleans or binary values to test for, and they are all independent. Suppose you have a student database. A set of independent booleans might be things like, male/female, home/on-campus, current/not-current, enrolled/not-enrolled, etc. Rather than store a boolean field for each one of those values, you could store just a single bit for each one. The male/female might be bit 1. enrolled/not might be bit 2.

Then you can use

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

as a test to see if no bits are turned on, except the "student is male" bit, which is ignored. Huh? Well, the bitwise OR returns a 1 for each bit that is on in either number. If the result of the bitwise OR above = 0x0001, that means there are no bits turned on in the bitfield, except maybe the first bit (0x0001), but you can't tell for sure whether the first bit is on, because it it is masked.

There is a corresponding && and &, which is logical AND and bitwise AND. They have the analogous behavior.

You can use

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

to see if the first bit is turned on in a bitfield.

EDIT: I can't believe I got voted down for this!

打小就很酷 2024-07-22 11:56:22

很好的答案,但让我补充一下,如果左侧表达式为 true,则不会评估 || 的右侧表达式。 对于评估术语 a) 性能密集型或 b) 产生副作用(罕见)的情况,请记住这一点。

Good answers, but let me add that the right-side expressions for || is not evaluated if the left-side expression is true. Keep this in mind for cases where the evaluation terms are a) performance-intensive or b) produce side effects (rare).

久伴你 2024-07-22 11:56:22

与迄今为止大多数答案所说的不同,其含义与 C++ 中的含义完全相同。

对于任意两个表达式 A 和 B 计算为布尔值,A || B 和 A | B 做几乎同样的事情。

一个 | B 对 A 和 B 进行计算,如果其中一个计算结果为 true,则结果为 true。

一个 || B 做了几乎相同的事情,只不过它首先评估 A,然后仅在必要时评估 B。 由于如果 A 或 B 为真,则整个表达式为真,因此如果 A 为真,则根本不需要测试 B。 所以|| 短路,并在可能的情况下跳过评估第二个操作数,其中 | 运算符将始终对两者进行评估。

| 的 | 运算符并不经常使用,而且通常不会产生任何影响。 我能想到的唯一常见情况是它会产生影响:这是

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

}

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

如果我们使用 | 运算符,无论 foo 是否为 null,都会调用 DoStuff()。

对于整数,只有 | 运算符已定义,并且是按位或,正如其他答案所描述的那样。 || 不过,没有为整数类型定义运算符,因此很难在 C# 中将它们混淆。

Unlike what most of the answers so far say, the meaning is not exactly the same as in C++.

For any two expressions A and B evaluating to booleans, A || B and A | B do almost the same thing.

A | B evaluates both A and B, and if one of them evaluates to true, the result is true.

A || B does almost the same thing, except it evaluates A first, and then only evaluates B if it is necessary. Since the entire expression is true if either A or B is true, B doesn't need to be tested at all if A is true. So || short-circuits, and skips evaluating the second operand when possible, where the | operator will always evaluate both.

The | operator isn't often used, and often it won't make a difference. The only common case I can think of where it'd make a difference is this:

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

}

This works because the DoStuff() member function is never called if the left test fails. That is, if foo is null, we don't call DoStuff on it. (which would give us a NullReferenceException).

If we'd used the | operator, DoStuff() would be called regardless of whether foo was null or not.

On integers, only the | operator is defined, and is a bitwise OR, as the other answers describe. The || operator isn't defined for integer types though, so it's hard to get them mixed up in C#.

萌梦深 2024-07-22 11:56:22

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

|| 是逻辑或运算符(布尔值)。 它仅适用于 true 和 false 值。

| is a bitwise OR operator (numeric, integer). it works by converting the numbers into binary and doing an OR for each of the corresponding digits. then again, numbers are already represented in binary in the computer, so no such conversion really takes place at runtime ;)

|| is a logical OR operator (boolean). it only works on true and false values.

鸢与 2024-07-22 11:56:22

以下内容可以在 C/C++ 中使用,因为它没有对布尔值的一流支持,它将每个带有“on”位的表达式视为 true,否则视为 false。 事实上,如果 x 和 y 是数字类型,则以下代码在 C# 或 Java 中不起作用。

if (x | y) 

因此,上述代码的显式版本是:

if ( (x | y) != 0)

在 C 语言中,任何带有“On”位的表达式都会得到 true

int i = 8;

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

int Joy = -10;

if (joy) // 在 C 中有效,结果为 true

现在,回到 C#

如果 x 和 y 是数字类型,则您的代码:if (x | y) 将不起作用。 你尝试过编译它吗? 它不会工作

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

    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

Jude 不会被打印两次,|| 是一个布尔运算符,许多C派生语言的布尔运算符都是短路的,短路的布尔表达式性能更高。

对于外行术语来说,当您说短路时,例如在 || 中 (或运算符),如果第一个表达式已经为真,则无需计算第二个表达式。 示例:if (answer == 'y' || answer == 'Y'),如果用户按小 y,程序不需要计算第二个表达式(answer == 'Y')。 那就是短路。

在上面的示例代码中,X 为 true,因此 || 上的 Y 运算符不会被进一步评估,因此没有第二个“Jude”输出。

即使 X 和 Y 是布尔类型,也不要在 C# 中使用此类代码:if (x | y)。 没有表现。

The following would work in C/C++ because it has no first class support for booleans, it treats every expression with "on" bit on them as true otherwise false. In fact, the following code would not work in C# or Java if x and y are of numeric types.

if (x | y) 

So the explicit version of above code is:

if ( (x | y) != 0)

In C, any expression which would have an "On" bit on them, results to true

int i = 8;

if (i) // valid in C, results to true

int joy = -10;

if (joy) // vaild in C, results to true

Now, back to C#

If x and y are of numeric type, your code: if (x | y) will not work. Have you tried compiling it? It will not work

But for your code, which I could assume x and y are of boolean types, so it will work, so the difference between | and || for boolean types, the || is short-circuited, the | is not. The output of the following:

    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; }
    }

is:

HeyJudeGet
Yes
HeyBack

Jude won't be printed twice, the || is a boolean operator, many C-derived languages boolean operators are short-circuited, boolean expressions are more performant if they are short-circuited.

As for layman terms, when you say short-circuited, for example in || (or operator), if the first expression is already true, no need to evaluate the second expression. Example: if (answer == 'y' || answer == 'Y'), if the user press small y, the program don't need to evaluate the second expression(answer == 'Y'). That's short-circuit.

On my sample code above, X is true, so the Y on || operator won't be evaluated further, hence no second "Jude" output.

Don't use this kind of code in C# even if X and Y are of boolean types: if (x | y). Not performant.

|煩躁 2024-07-22 11:56:22

第一个按位运算符作用于两个数值并产生第三个数值。

如果有二进制变量

a = 0001001b;
b = 1000010b;

,则

a | b == 1001011b;

也就是说,如果任一操作数中的某个位也为 1,则结果中的某个位为 1。 (为了清楚起见,我的示例使用 8 位数字)

“双管道”|| 是一个逻辑 OR 运算符,它接受两个布尔值并产生第三个布尔值。

The first, bitwise operator works on two numerical values and results in a third one.

If you have binary variables

a = 0001001b;
b = 1000010b;

then

a | b == 1001011b;

That is, a bit in the result is 1 if it is also 1 in either of the operands. (My example uses 8-bit numbers for clarity's sake)

The "double pipe" ||, is a logical OR operator that takes two boolean values and results in a third.

荒岛晴空 2024-07-22 11:56:22

无需深入研究任何方式、形状或形式的细节,这是一个真正的外行版本。

想想“|” 英语中直接的“或”; 想想“||” 英语中的“否则”。

同样地想想“&” 英语中的“and”; 想想“&&” 英语中的“也”。

如果你自己用这些术语读一个表达,它们通常会更有意义。

Without delving into the details in any way, shape, or form, here's a real layman's version.

Think of "|" as a straight "or" in english; think of "||" as "or else" in english.

Similarly think of "&" as "and" in english; think of "&&" as "and also" in english.

If you read an expression to yourself using these terms, they often make a lot more sense.

青春如此纠结 2024-07-22 11:56:22

强烈建议阅读 Dotnet Mob 的这篇文章

对于 OR 逻辑运算,如果它的任何操作数被评估为 true 那么
整个表达式被评估为 true

这就是 || 运算符会这样做 - 当它发现 true 时,它​​会跳过剩余的评估。 同时| 运算符评估其完整操作数以评估整个表达式的值。

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
}

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


Consider the following Code Snippet

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

这种效应称为副作用,实际上可以在短路逻辑运算符的表达式右侧看到

参考:C# 中的短路评估

Strongly recommend to read this article from Dotnet Mob

For OR logical operation if any of it's operand is evaluated to true then
whole expression is evaluated to true

this is what || Operator does - it skips the remaining evaluation when it found a true. While | Operator evaluate it's complete operands to asses the value of whole 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
}

It is better to use Short Circuited version of Logical Operator Whether it is OR(||) or AND(&&) Operator.


Consider the following Code Snippet

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

This effect is called side effect, actually seen in right side of expression in short circuited logical operators

Reference : Short-circuit Evaluation in C#

桃酥萝莉 2024-07-22 11:56:22

尽管已经正确地说过并回答了,但我想我应该添加一个真正的外行人的答案,因为很多时候这就是我在这个网站上的感受:)。 另外,我将添加 & 的示例 与&& 因为它是相同的概念

| vs ||

基本上你倾向于使用 || 当您只想评估第二部分时,如果第一部分为 FALSE。 所以这:

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

与这相同

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

这可能是节省处理时间的一种方法。 如果 func2() 需要很长时间来处理,而 func1() 已经为 true 时,您就不会愿意执行此操作。

& vs &&

在 & 的情况下 与&& 这是一种类似的情况,如果第一部分为 TRUE,则仅评估第二部分。 例如,这:

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

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

这可能是必要的,因为 func2() 可能首先依赖于 func1() 为 true。 如果您使用 & 并且 func1() 评估为 false,& 无论如何都会运行 func2() ,这可能会导致运行时错误。

外行人杰夫

Although it's already been said and answered correctly I thought I'd add a real layman's answer since alot of the time that's what I feel like on this site :). Plus I'll add the example of & vs. && since it's the same concept

| vs ||

Basically you tend to use the || when you only wnat to evaluate the second part IF the first part it FALSE. So this:

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

is the same as

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

This may be a way to save processing time. If func2() took a long time to process, you wouldn't want to do it if func1() was already true.

& vs &&

In the case of & vs. && it's a similar situation where you only evaluate the second part IF the first part is TRUE. For example this:

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

is the same as

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

This can be necessary since func2() may depend on func1() first being true. If you used & and func1() evaluated to false, & would run func2() anyways, which could cause a runtime error.

Jeff the Layman

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文