14

いくつかのコードを見直していたところ、次のようなものを見つけました。

public class MyClass
{
    public bool IsEditable { get; set; }

    public void HandleInput()
    {
        if (IsEditable.Equals(false))
        {
            //do stuff
        }
    }
}

私の知る限り、(IsEditable.Equals(false))は と同じです(IsEditable == false)(また、 とも同じです(!IsEditable))。

個人的な好み以外に、特にsを比較するために使用された場合.Equals()、との間に違いはありますか?==bool

4

8 に答える 8

12

これは主に可読性の問題です。==それは私が見慣れているものなので、 私は通常使用します。

具体的にはブール値を使用すると、それらを比較する必要はまったくありません

if(!IsEditable)

十分であろう

if (val == false)ただし、コードを変更する必要があるときに読み間違えない ように、自分で書くこともあります。

于 2012-11-28T21:37:04.640 に答える
11

実際、などの基本的なタイプintの場合、呼び出しと、CILにそのようなタイプを処理するための指示があるため、呼び出しにboolは違いがあります。呼び出しは、値のボックス化と仮想メソッド呼び出しを強制しますが、を使用すると、単一のCIL命令が使用されます。Equals()==Equals()==

!valuevalue == false少なくとも.NET4.0にバンドルされているMicrosoftのC#コンパイラでは、実際には同じです。

したがって、以下の方法での比較

public static int CompareWithBoxingAndVirtualMethodCall(bool value)
{
    if (value.Equals(false)) { return 0; } else { return 1; }
}

public static int CompareWithCILInstruction(bool value)
{
    if (value == false) { return 0; } else { return 1; }
    if (!value) { return 0; } else { return 1; } // comparison same as line above
}

次のCIL命令にコンパイルされます。

// CompareWithBoxingAndVirtualMethodCall

ldarga.s 'value'
ldc.i4.0
call instance bool [mscorlib]System.Boolean::Equals(bool) // virtual method call
brfalse.s IL_000c // additional boolean comparison, jump for if statement

// CompareWithCILInstruction

ldarg.0
brtrue.s IL_0005 // actual single boolean comparison, jump for if statement
于 2012-11-28T22:15:22.773 に答える
7

このEquals方法はかなり遅いように見えます。デバッグ モードでは約 2.7 倍、リリース モードでは 7 倍以上です。

これが私の迅速で汚いベンチマークです:

public static void Main() {
    bool a = bool.Parse("false");
    bool b = bool.Parse("true");
    bool c = bool.Parse("true");
    var sw = new Stopwatch();
    const int Max = 1000000000;
    int count = 0;
    sw.Start();
    // The loop will increment count Max times; let's measure how long it takes
    for (int i = 0; i != Max; i++) {
        count++;
    }
    sw.Stop();
    var baseTime = sw.ElapsedMilliseconds;
    sw.Start();
    count = 0;
    for (int i = 0; i != Max; i++) {
        if (a.Equals(c)) count++;
        if (b.Equals(c)) count++;
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
    sw.Reset();
    count = 0;
    sw.Start();
    for (int i = 0; i != Max; i++) {
        if (a==c) count++;
        if (b==c) count++;
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
    sw.Reset();
    count = 0;
    sw.Start();
    for (int i = 0; i != Max; i++) {
        if (!a) count++;
        if (!b) count++;
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
}

これを実行すると、次の結果が生成されます。

デバッグモードで

8959
2950
1874

リリースモードで

5348
751
7

Equalsが最も遅いようです。==と の間にはほとんど差がないように見えます!=。しかし、if (!boolExpr)明らかに勝者のようです。

于 2012-11-28T21:48:17.570 に答える
2

System.Boolean を逆コンパイルして見ると、It's Equals オーバーロードは次のように定義されています。

public override bool Equals(object obj)
{
  if (!(obj is bool))
    return false;
  else
    return this == (bool) obj;
}

public bool Equals(bool obj)
{
  return this == obj;
}

C# コンパイラのオプティマイザと .Net JIT コンパイラは、少なくともリリース/最適化されたコンパイルでは、これらをインライン化するのに十分スマートであり、まったく同じになると思います。

于 2012-11-28T22:50:55.097 に答える
-1

ここから引用した次の引用を見てください:

Equalsメソッドは、System.Objectで定義された単なる仮想メソッドであり、どのクラスがそうすることを選択した場合でもオーバーライドされます。==演算子は、クラスによってオーバーロードできる演算子ですが、通常はIDの動作をします。

==がオーバーロードされていない参照型の場合、2つの参照が同じオブジェクトを参照しているかどうかを比較します。これは、System.ObjectでのEqualsの実装とまったく同じです。

つまり、Equalsとにかく実際には==を実行しているだけです。

于 2012-11-28T21:54:28.437 に答える
-1

==は常に よりも優れてい.Equalsます。整数比較の場合、==は よりも高速に実行されます.Equals。以下のテストでは、経過時間は==157を使用して.Equalsいますが、経過時間は 230 です。

class Program
 {        
   static void Main(string[] args)
    {

        Program programObj = new Program();
            programObj.mymethod();
            programObj.mynextmethod();

    }
    void mynextmethod()
    {
        var watch = Stopwatch.StartNew();

        for (int i = 0; i < 60000000; i++)
        {
            int j = 0;
            if (i.Equals(j))

                j = j + 1;
        }
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
        Console.WriteLine("Time take in method" + elapsedMs);


        Console.ReadLine();
    }
    void mymethod()
    {
        var watch = Stopwatch.StartNew();

        for (int i = 0; i < 60000000; i++)
        {
            int j = 0;
            if (i == j)

                j = j + 1;
        }
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
        Console.WriteLine("Time take in method" + elapsedMs);
    }
}
于 2014-08-27T09:49:23.013 に答える
-1

この場合、ブール値では違いはありませんが、他の組み込みの非参照型では違いがあります。

==変換でき .Equalsない場合は、型の変換を許可します

于 2012-11-28T21:45:41.093 に答える