好的,我已经多次阅读了这方面的内容,但我仍然没有听到一种清晰、易于理解(而且易于记忆)的学习以下两个概念之间区别的方法:
if (x | y)
并且。if (x || y)
在C#的上下文中,...能否有人帮我学习这个基本真理,以及C#如何特别处理它们(因为它们似乎做了同样的事情)。如果一个给定的代码片段在它们之间的差异是无关紧要的,那么我应该默认使用哪个作为最佳实践?
好的,我已经多次阅读了这方面的内容,但我仍然没有听到一种清晰、易于理解(而且易于记忆)的学习以下两个概念之间区别的方法:
if (x | y)
并且。if (x || y)
在C#的上下文中,...能否有人帮我学习这个基本真理,以及C#如何特别处理它们(因为它们似乎做了同样的事情)。如果一个给定的代码片段在它们之间的差异是无关紧要的,那么我应该默认使用哪个作为最佳实践?
||
是逻辑或(logical-or)运算符。点击这里可以查看详细资料。它的返回值为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 || b
与a | b
是完全相同的,唯一的例外是当a
为真时不会计算b
。因此,||
被称为“短路运算符”。
正如所述,差异并不无关紧要,因此这个问题在某种程度上是无意义的。至于“最佳实践”,并没有一个:你只需使用正确的运算符即可。一般来说,人们更喜欢将布尔操作数中的如果两个代码之间的差异是无关紧要的,那么我应该默认使用哪一个作为最佳实践?
||
与|
相比较,因为你可以确保它不会产生不必要的副作用。当使用布尔操作数时,|
运算符是一个逻辑运算符,就像 ||
一样,但不同的是,||
运算符进行短路评估,而 |
运算符则不会。
这意味着使用 |
运算符时始终会评估第二个操作数,但使用 ||
运算符时,只有在第一个操作数评估为 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,则只有第二个操作数会被评估,因此您知道如果评估第二个操作数,则可以安全地使用字符串引用,因为它不可能为空。int a = 0;
int b = 0;
bool x = (a != 0 || ++b != 0);
// 这里b仍然是0,因为"++b != 0"操作数没有被评估
但是a == 0,所以第一条语句被评估为false,因此第二部分被评估。 - Davy8它们不是同一个东西。其中一个是按位或,另一个是逻辑或。
X || Y 是逻辑或,与 "X 或 Y" 相同,适用于布尔值。它通常用于条件语句或测试中。在这种情况下,X 和 Y 可以替换为任何评估为布尔值的表达式。例如:
if (File.Exists("List.txt") || x > y ) { ..}
如果两个条件中的任意一个为真,则该子句求值为真。如果第一个条件为真(如果文件存在),则第二个条件不需要并且将不会被评估。
单个管道符号(|)是按位或运算符。要知道这意味着什么,您必须了解计算机中数字的存储方式。假设您有一个保存值为15的16位数量(Int16)。它实际上以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#中使用按位或运算符(单个管道符号)来测试特定一组位中是否打开了一个或多个。如果您有,假设您有一个学生数据库,那么一组独立布尔值或二进制值可能是像男/女、家庭/校园、当前/非当前、已注册/未注册等。 您可以为每个值存储一个位,而不是为每个值存储布尔字段。男/女可能是第1位。已注册/未注册可能是第2位。
然后您可以使用
if ((bitfield | 0x0001) == 0x0001) { ... }
作为一个测试,以查看是否没有开启任何位,除了“学生是男性”的位,这个位被忽略了。什么?好吧,按位或运算对于在任一数字中打开的每个位返回1。如果上面的按位或运算的结果= 0x0001,则表示位字段中没有打开任何位,除了可能第一个位(0x0001),但你不能确定第一个位是否打开,因为它被掩码了。
有相应的&&和&运算符,它们是逻辑与和按位与。它们具有类似的行为。
你可以使用
if ((bitfield & 0x0001) == 0x0001) { ... }
检查位域中的第一位是否已打开。
编辑:我无法相信我因此被投票否决!
||
表达式。在评估术语是性能密集型或产生副作用(罕见)的情况下,请记住这一点。if ( foo != null || foo.DoStuff()){ // assuming DoStuff() returns a bool
}
if (foo == null || foo.DoStuff())
。因此,如果 foo == null
,则表达式返回 true
而不会进一步评估;否则,foo
不是 null,因此第一部分返回 false 并且评估第二部分,这可以实现,因为在这种情况下 foo
不为 null。 - Massimiliano Kraus| 是位运算符(数字,整数)。它通过将数字转换为二进制并对应每个数字进行OR操作来工作。然而,在计算机中,数字已经以二进制表示,因此在运行时不需要进行任何转换 ;)
|| 是逻辑或运算符(布尔值)。它仅适用于真和假值。
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; }
}
is:
HeyJudeGet
Yes
HeyBack
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
}
int i=0;
if(false||(++i<10))//Now i=1
{
//Some Operations
}
if(true||(++i<10))//i remains same, ie 1
{}
不深入探讨任何细节,这里是一个真正的外行人版本。
将"|"看作英语中的直接"或(or)"; 将"||"看作英语中的"否则(or else)"。
同样地,将"&"看作英语中的"和(and)";将"&&"看作英语中的"并且(and also)"。
如果您使用这些术语向自己阅读表达式,它们通常会更有意义。
a = 0001001b;
b = 1000010b;
a | b == 1001011b;
也就是说,结果中的一位如果在两个操作数中任意一个为1,则该位为1。 (我的例子使用8位数字只是为了清晰起见)
"双竖线" || 是逻辑或运算符,它接受两个布尔值并得出第三个值。