if (string) vs if (bool) in C#
本文关键字:if in vs string bool | 更新日期: 2023-09-27 18:08:56
是否有明显的性能/代码质量差异,如果你使用一个字符串比较在一个"if"开头,而不是布尔?
字符串示例:
string isTrue = "true";
if (isTrue == "true"){
// do something
}
bool:
的示例bool isTrue = true;
if (isTrue){
//do something
}
我通常使用bool进行这种比较,但我在网上看到过这两种变化
基于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
你可以看到比较字符串需要调用方法,比较bool不需要这个。
性能方面比较两个bool(位是否设置?)比比较两个字符串更快。
代码质量明智的选择#2是首选。在这种情况下,当您有可用的布尔值时,实际上没有任何理由使用字符串比较。它会使你的代码更混乱,更难以理解和维护。
我决定试一试,并创建了以下代码:
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引用相同的字符串。然而,比较两个字符串总是按值进行的,所以它实际上必须遍历整个字符串。然而,如果字符串被拘禁(保存相同的引用)并将它们转换为对象,则会强制进行by ref比较——这将迫使它成为一个不昂贵的操作,并且实际上具有与检查布尔值相同的性能。
**应该有一个转换为对象的开销,但根据我的测试,它似乎不明显。
关于你的问题
显然,检查字符串比检查布尔值的代价要高得多,并且是由字符串的长度和它们的相似程度决定的。所以,使用字符串并不是一个好的选择。
然而如果你确实使用字符串来检查相等性-你应该确保它们拥有相同的引用(str = str2
是一个例子),并通过引用来检查相等性。
(所有这些都不是很明显,但仍然)
在您的示例中,bool比较将比字符串比较保持更好的代码质量。