OR运算符在C#
回答
不,你可以这样做:
if (new[] { "b", "c" }.Contains(a))
如果你有LINQ扩展可用,但几乎没有改善。
在回答有关性能的评论,这里的一些基本的计时码。请注意,代码必须以批判的眼光来看待,我可能在这里做了一些使时间偏离的事情。
结果第一:
||, 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
所有的代码被执行两次,也只有通过NR。据报告2,以消除等式中的JITting开销。两个遍都执行了每种类型的检查一百万次,并且在要找到的元素是找到它的元素之一(即,if语句将执行其块)以及一旦元素不是(该块不会执行)。报告每个的时间。我测试了预构建数组和每次构建的数组,这部分我不确定编译器推导并优化了多少,这里可能存在缺陷。
在任何情况下,使用switch-statement(无论是否首先实际使用字符串)都会给出与简单或声明大致相同的结果,这是预期的结果,而数组查找很多更昂贵,这对我来说也是预料之中的。
请修改代码,并纠正(或评论)它,如果有问题。
而这里的源代码,而长:
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" };
}
}
}
如果数组是静态分配的,那么性能测试可能会很有趣(如果表达式花费的时间足够长以便根据时间开销进行测量)。 – Richard 2009-05-05 19:46:24
据我所知,这是不是一种选择。
那么,最接近你可以得到的是:
switch (a) {
case "b":
case "c":
// variable a is either "b" or "c"
break;
}
接受的答案是少代码,但使用switch语句的开销较少,我相信。 – 2009-05-05 17:49:50
我推荐此解决方案。首先,它更具可读性。其次,它的开销较小。第三,如果逻辑必须在未来发生变化,则维护起来更容易。 – 2009-05-05 17:53:18
接受的答案可能适合单行,但这个不会为数组分配额外的内存。 – Kon 2009-05-05 18:35:20
不,不与语法。但是有很多选项可以编码。
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)) { }
也许你可以做一些运算符重载,让你的语法的工作,但是这真的取决于你想要达到什么目的,难以从简单的例子来告诉。
不,这不是如何运算符(||)如何在C#中工作。
另一种解决方案,但它使代码的可读性,是创建检查你想要的值的函数,类似于:
public static bool Any(object a, params object[] b)
{
foreach(object item in b)
{
if(a == b)
{
return true;
}
}
return false;
}
您可以使用正则表达式:
if(Regex.IsMatch(a, "b|c"))
如果“A”可能比一个字符使用这种较长的内容:
if(Regex.IsMatch(a, "^(b|c)$"))
ÿ你可以在某些情况下。也就是说,标记枚举:
[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
等同于:
if((a & MyEnum.B) > 0 || (a & MyEnum.C) > 0)
// do something
这样做的原因有位掩码做。在二进制中,
None = 00000
A = 00001
B = 00010
C = 00100
D = 01000
所以当我们使用|运算符,我们进行一点一点的比较,查找列中的任意1并将它们复制到结果中。如果没有1的列,你复制一个0
B 00010
& C 00100
---------
00110
然后当我们应用&经营者,我们复制一个1
(B & C) 00110
& (a = B) 00010
---------------
00010
前1个在每列中的所有行
这是> 0,因此返回true。
奇怪的是,这是最有效的方法,因为它为您节省了一个数值比较(>)和一个逻辑运算符(||),它可以完成所有那些奇怪的短路和什么。
- 1. 运算符[&]在C++
- 2. 运算符()在C++
- 3. C++运算符 ''
- 4. 运算符[] [] C++
- 5. C++:运算符重载,运算符+
- 6. 困惑?运算符在c#
- 7. 模数运算符在C#
- 8. +运算符重载在C++
- 9. 与?运算符在C#
- 10. 重载[] []在C++运算符
- 11. C++ typeid运算符
- 12. C#Lambda运算符
- 13. C#coalesce运算符
- 14. C++ overload []运算符
- 15. 点运算符C++
- 16. C++ typeof运算符
- 17. XOR运算符C++
- 18. XOR运算符C
- 19. C++运算符 - >
- 20. C++ delete []运算符
- 21. :c/C++中的运算符
- 22. 字符串运算符C++
- 23. C++运算符在已重载的运算符中重载
- 24. 替代在C++中使用%运算符和/运算符
- 25. 运算符在C++帮助中重载流提取运算符
- 26. 在c + +运算符重载(比较运算符)
- 27. 在条件运算符中增加运算符c
- 28. C#按位运算符在字符上
- 29. C中的代字符运算符在
- 30. 定时运算符+,运算符,运算符*和运算符/
您确定要使用|运算符(二进制或)而不是|| (逻辑或)? – 2009-05-05 17:42:17
...你不是说||运营商? – 2009-05-05 17:42:36
正确!我编辑了这篇文章。 – 2009-05-05 17:47:33