C#中的OR运算符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/826081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OR operator in C#
提问by Saif Khan
Can I achieve
我能达到吗
if (a == "b" || "c")
instead of
代替
if (a == "b" || a== "c")
?
?
采纳答案by Lasse V. Karlsen
No, you can do:
不,你可以这样做:
if (new[] { "b", "c" }.Contains(a))
if you have the LINQextensions available, but that's hardly an improvement.
如果您有可用的LINQ扩展,但这几乎没有改进。
In response to the comment about performance, here's some basic timing code. Note that the code must be viewed with a critical eye, I might have done things here that skew the timings.
为了回应关于性能的评论,这里有一些基本的计时代码。请注意,必须以批判的眼光查看代码,我可能在这里做了一些歪曲时间的事情。
The results first:
先上结果:
||, not found: 26 ms
||, found: 8 ms
array.Contains, not found: 1407 ms
array.Contains, found: 1388 ms
array.Contains, inline array, not found: 1456 ms
array.Contains, inline array, found: 1427 ms
switch-statement, not interned, not found: 26 ms
switch-statement, not interned, found: 14 ms
switch-statement, interned, not found: 25 ms
switch-statement, interned, found: 8 ms
All the code was executed twice, and only pass nr. 2 was reported, to remove JITting overhead from the equation. Both passes executed each type of check one million times, and executed it both where the element to find was one of the elements to find it in (that is, the if-statement would execute its block), and once where the element was not (the block would not execute). The timings of each is reported. I tested both a pre-built array and one that is built every time, this part I'm unsure how much the compiler deduces and optimizes away, there might be a flaw here.
所有的代码都执行了两次,并且只通过了nr。2 被报告,以从等式中去除 JITting 开销。两次传递都执行了每种类型的检查一百万次,并且在要查找的元素是要查找它的元素之一的地方执行它(即 if 语句将执行其块),并且在元素不是的地方执行一次(该块不会执行)。报告了每个的时间。我测试了预先构建的数组和每次构建的数组,这部分我不确定编译器推断和优化了多少,这里可能存在缺陷。
In any case, it appears that using a switch-statement, with or without interning the string first, gives roughly the same results as the simple or-statement, which is to be expected, whereas the array-lookup is much more costly, which to me was also expected.
在任何情况下,使用 switch 语句,无论是否先插入字符串,都会给出与简单 or 语句大致相同的结果,这是可以预料的,而数组查找的成本要高得多,这对我来说也是预料之中的。
Please tinker with the code, and correct (or comment) it if there's problems.
请修改代码,如果有问题,请更正(或评论)它。
And here's the source code, rather long:
这是源代码,相当长:
using System;
using System.Linq;
using System.Diagnostics;
namespace StackOverflow826081
{
class Program
{
private const Int32 ITERATIONS = 1000000;
static void Main()
{
String a;
String[] ops = CreateArray();
Int32 count;
Stopwatch sw = new Stopwatch();
Int32 pass = 0;
Action<String, Int32> report = delegate(String title, Int32 i)
{
if (pass == 2)
Console.Out.WriteLine(title + ": " + sw.ElapsedMilliseconds + " ms");
};
for (pass = 1; pass <= 2; pass++)
{
#region || operator
a = "a";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (a == "b" || a == "c")
{
count++;
}
}
sw.Stop();
report("||, not found", count);
sw.Reset();
a = "b";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (a == "b" || a == "c")
{
count++;
}
}
sw.Stop();
report("||, found", count);
sw.Reset();
#endregion
#region array.Contains
a = "a";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (ops.Contains(a))
{
count++;
}
}
sw.Stop();
report("array.Contains, not found", count);
sw.Reset();
a = "b";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (ops.Contains(a))
{
count++;
}
}
sw.Stop();
report("array.Contains, found", count);
sw.Reset();
#endregion
#region array.Contains
a = "a";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (CreateArray().Contains(a))
{
count++;
}
}
sw.Stop();
report("array.Contains, inline array, not found", count);
sw.Reset();
a = "b";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
if (CreateArray().Contains(a))
{
count++;
}
}
sw.Stop();
report("array.Contains, inline array, found", count);
sw.Reset();
#endregion
#region switch-statement
a = GetString().Substring(0, 1); // avoid interned string
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
switch (a)
{
case "b":
case "c":
count++;
break;
}
}
sw.Stop();
report("switch-statement, not interned, not found", count);
sw.Reset();
a = GetString().Substring(1, 1); // avoid interned string
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
switch (a)
{
case "b":
case "c":
count++;
break;
}
}
sw.Stop();
report("switch-statement, not interned, found", count);
sw.Reset();
#endregion
#region switch-statement
a = "a";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
switch (a)
{
case "b":
case "c":
count++;
break;
}
}
sw.Stop();
report("switch-statement, interned, not found", count);
sw.Reset();
a = "b";
sw.Start();
count = 0;
for (Int32 index = 0; index < ITERATIONS; index++)
{
switch (a)
{
case "b":
case "c":
count++;
break;
}
}
sw.Stop();
report("switch-statement, interned, found", count);
sw.Reset();
#endregion
}
}
private static String GetString()
{
return "ab";
}
private static String[] CreateArray()
{
return new String[] { "b", "c" };
}
}
}
回答by Ian Jacobs
To my knowledge that isn't an option.
据我所知,这不是一个选择。
回答by Guffa
Well, the closest to that you can get is:
好吧,你能得到的最接近的是:
switch (a) {
case "b":
case "c":
// variable a is either "b" or "c"
break;
}
回答by Daniel Brückner
No, not with that syntax. But there are many options to code that.
不,不是那种语法。但是有很多选择来编码。
if ("bc".Contains(a)) { } // Maybe check a.Length == 1, too.
if ((a[0] & 0x62) == 0x62) { } // Maybe check a.Length == 1, too.
if (new String[] { "b", "c" }.Contains(a)) { }
Maybe you could do some operator overloading and get your syntax working, but this really depends on what you want to achieve and is hard to tell from your simple example.
也许您可以进行一些运算符重载并使语法正常工作,但这实际上取决于您想要实现的目标,并且很难从您的简单示例中看出。
回答by Jake Basile
No, this isn't how the or operator (||) works in C#.
不,这不是 C# 中 or 运算符 (||) 的工作方式。
An alternate solution, though it makes the code less readable, is to create a function that checks for the value you want, something similar to:
另一种解决方案,虽然它降低了代码的可读性,但创建一个函数来检查您想要的值,类似于:
public static bool Any(object a, params object[] b)
{
foreach(object item in b)
{
if(a == b)
{
return true;
}
}
return false;
}
回答by TruthStands
You can use Regular Expressions:
您可以使用正则表达式:
if(Regex.IsMatch(a, "b|c"))
If the contents of "a" can be longer than one character use this:
如果“a”的内容可以长于一个字符,请使用:
if(Regex.IsMatch(a, "^(b|c)$"))
回答by Daniel Moore
You can in certain situations. Namely, flagged enumerations:
您可以在某些情况下。即,标记的枚举:
[Flags]
enum MyEnum {
None = 0,
A = 1,
B = 2,
C = 4,
D = 8
}
//...
MyEnum a = MyEnum.B
if((a & (MyEnum.B | MyEnum.C)) > 0)
// do something
is equivalent to :
相当于:
if((a & MyEnum.B) > 0 || (a & MyEnum.C) > 0)
// do something
The reason for this has to do with bit masks. In binary,
其原因与位掩码有关。在二进制中,
None = 00000
A = 00001
B = 00010
C = 00100
D = 01000
So when we use the | operator, we do a bit-by-bit comparison looking for any 1's in the column and copy them into the result. If there are no 1's in the column, you copy a 0.
所以当我们使用 | 运算符,我们进行逐位比较以查找列中的任何 1 并将它们复制到结果中。如果列中没有 1,则复制 0。
B 00010
& C 00100
---------
00110
Then when we apply the & operator, we look for 1's in all rows in each column before copying a 1.
然后当我们应用 & 运算符时,我们在复制 1 之前在每列的所有行中查找 1。
(B & C) 00110
& (a = B) 00010
---------------
00010
Which is > 0, thus returning true.
哪个 > 0,因此返回 true。
Oddly enough, this is the most efficient way to do it, since it saves you a numerical comparison (>) and a logical operator (||), which does all that fancy short circuiting and whatnot.
奇怪的是,这是最有效的方法,因为它为您节省了数字比较 (>) 和逻辑运算符 (||),它们可以完成所有花哨的短路等操作。