14

我正在查看一些代码,我发现一些看起来像这样的东西:

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

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

据我所知,(IsEditable.Equals(false))(IsEditable == false)(也与(!IsEditable))相同。

.Equals()除了个人喜好之外, and之间有什么区别==特别是用于比较bools时?

4

8 回答 8

12

这主要是一个可读性问题。我通常会使用==,因为那是我习惯看的。

特别是对于布尔值,您根本不必比较它们

if(!IsEditable)

就足够了

虽然,有时我自己会写一些东西,if (val == false)只是为了确保在我必须修改代码时不会误读它。

于 2012-11-28T21:37:04.640 回答
11

事实上,对于诸如 等基本类型int,调用和bool是有区别的,因为 CIL 有处理这些类型的指令。调用会强制对值进行装箱并进行虚拟方法调用,而使用会导致使用单个 CIL 指令。Equals()==Equals()==

!value并且value == false实际上是相同的,至少在与 .NET 4.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 倍,在发布模式下是七倍多。

这是我快速而肮脏的基准:

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 并查看它,它的 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

有区别-至少在.NET 4.8中-我相信原因是由于Oliver Hanappi的回答中描述的拳击:

static void Main(string[] args)
{
     object lhs = true;
     object rhs = true;
 
     Console.WriteLine($"Are Equal - {(lhs == rhs ? "Yes" : "No")}"); // Outputs no
     Console.WriteLine($"Are Equal - {(lhs.Equals(rhs) ? "Yes" : "No")}"); // Outputs yes
     Console.ReadLine();
}
于 2020-06-23T00:44:25.980 回答
-1

在这种情况下,对于 bool,它没有任何区别,但是对于其他内置的非引用类型,它可以。

==如果不能,则允许类型 .Equals转换

于 2012-11-28T21:45:41.093 回答
-1

看一下从这里摘录的以下引用:

Equals 方法只是在 System.Object 中定义的一个虚拟方法,并且被选择这样做的任何类覆盖。== 运算符是一个可以被类重载的运算符,但通常具有标识行为。

对于 == 没有被重载的引用类型,它会比较两个引用是否引用同一个对象——这正是 Equals 在 System.Object 中的实现。

所以简而言之,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 回答