문제

달성 할 수 있습니까?

if (a == "b" || "c")

대신에

if (a == "b" || a== "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-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" };
        }
    }
}

다른 팁

글쎄, 당신이 얻을 수있는 가장 가까운 것은 다음과 같습니다.

switch (a) {
   case "b":
   case "c":
      // variable a is either "b" or "c"
      break;
}

내 아는 것은 선택 사항이 아닙니다.

정규 표현식을 사용할 수 있습니다.

if(Regex.IsMatch(a, "b|c"))

"a"의 내용이 하나보다 길 수있는 경우 다음을 사용합니다.

if(Regex.IsMatch(a, "^(b|c)$"))

아니요, 그 구문은 아닙니다. 그러나 코딩 할 수있는 많은 옵션이 있습니다.

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

어쩌면 당신은 일부 운영자 과부하를하고 구문을 작동시킬 수 있지만, 이는 실제로 달성하고자하는 것에 달려 있으며 간단한 예에서 말하기 어렵습니다.

특정 상황에서는 할 수 있습니다. 즉, 신고 된 열거 :

[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을 복사하기 전에 각 열의 모든 행에서 1을 찾습니다.

  (B & C) 00110
& (a = B) 00010
---------------
          00010

이것은> 0이므로 TRUE가 돌아옵니다.

이상하게도, 이것은 가장 효율적인 방법입니다. 수치 비교 (>)와 논리 연산자 (||)를 절약 할 수 있기 때문에 멋진 단락과 그 일을 수행하기 때문입니다.

아니요, 이것은 OR 연산자 (||)가 C#에서 작동하는 방식이 아닙니다.

대체 솔루션은 코드를 읽기 쉽지 않지만 원하는 값을 확인하는 기능을 작성하는 것입니다.

public static bool Any(object a, params object[] b)
{
    foreach(object item in b)
    {
        if(a == b)
        {
            return true;
        }
    }
    return false;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top