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