在C#中if(string)vs if(bool)

时间:2016-09-27 09:40:26

标签: c# if-statement boolean compare

如果在“if”而不是布尔值的开头使用字符串进行比较,性能/代码质量是否会有明显差异?

字符串示例:

string isTrue = "true";
if (isTrue == "true"){
  // do something
}

bool示例:

bool isTrue = true;
if (isTrue){
   //do something
}

我通常使用bool进行这种比较,但我在网上看到了这两种变化。

4 个答案:

答案 0 :(得分:4)

基于tryroslyn

上生成的代码

代码:

using System;
public class C {
    public void M() {
        string isStringTrue = "true";
        if (isStringTrue == "true")
        {
            // do something
        }              

        bool isBoolTrue = true;
        if (isBoolTrue)
        {
            //do something
        }
    }
}

制作IL代码:

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit C
    extends [mscorlib]System.Object
{
    // Methods
    .method public hidebysig 
        instance void M () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 34 (0x22)
        .maxstack 2
        .locals init (
            [0] string,
            [1] bool,
            [2] bool,
            [3] bool
        )

        IL_0000: nop
        IL_0001: ldstr "true"
        IL_0006: stloc.0
        IL_0007: ldloc.0
        IL_0008: ldstr "true"
        IL_000d: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_0012: stloc.2
        IL_0013: ldloc.2
        IL_0014: brfalse.s IL_0018
        IL_0016: nop
        IL_0017: nop
        IL_0018: ldc.i4.1
        IL_0019: stloc.1
        IL_001a: ldloc.1
        IL_001b: stloc.3
        IL_001c: ldloc.3
        IL_001d: brfalse.s IL_0021
        IL_001f: nop
        IL_0020: nop
        IL_0021: ret
    } // end of method C::M

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x207e
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method C::.ctor

} // end of class C

正如你可以看到比较字符串需要调用方法,比较bools不需要这个。

答案 1 :(得分:3)

性能方面,比较两个bool(比特是否设置?)与比较两个字符串比较快。

代码质量明智的替代#2更喜欢。当你有可用的布尔值时,在这种情况下使用字符串比较真的没有任何理由。它会混淆并使您的代码更难理解和维护。

答案 2 :(得分:1)

我决定尝试一下并创建以下代码:

Stopwatch watch = new Stopwatch();
string str1 = "MyTest";
string str2 = str1.Substring(0,2)+"Test";
watch.Start();
if(str1 == str2)
{
    Console.WriteLine("str1 == str2");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
watch.Restart();
var obj1 = (object)str1;
var obj2 = (object)str2;
if(obj1 == obj2)
{
    Console.WriteLine("obj1 == obj2");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
string str3 = "MyTest";
string str4 = "MyTest";
watch.Restart();
if (str3 == str4)
{
     Console.WriteLine("str3 == str4");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
watch.Restart();
watch.Restart();
var obj3 = (object)str3;
var obj4 = (object)str4;
if (obj3 == obj4)
{
    Console.WriteLine("obj3 == obj4");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
if (true)
{
     Console.WriteLine("true");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);

它产生了以下结果:

//str1 == str2  
//00:00:00.0564061 
//00:00:00.0000116 
//str3 == str4
//00:00:00.0103047 
//obj3 == obj4
//00:00:00.0000004 
//true 
//00:00:00.0000004

关于此事的两分钱 - 默认情况下,字符串,如果它们是“硬编码”的,则由系统实现,因此str3和str4引用相同的字符串。但是,比较两个字符串总是按值,因此它实际上必须遍历整个字符串。 但是,如果字符串被中断(保持相同的引用)并将它们转换为对象,则会强制执行ref refer - 并强制它成为非昂贵的操作,并且实际上具有与检查布尔值相同的性能。 / p>

**应该有转换为对象的开销,但根据我的测试,它似乎不明显。

关于您的问题

显然,检查字符串比检查布尔值要昂贵得多,并且由字符串的长度以及它们的相似程度决定。所以,使用字符串不是一个好的选择。

<强>然而

如果你确实使用字符串来检查相等性 - 你应该确保它们保持相同的引用(str = str2是一个例子)并通过ref检查相等性。

(所有这些都不是真的很明显,但仍然)

答案 3 :(得分:0)

在您的情况下,bool比较将保持比字符串比较更好的代码质量。