使用 'is' 关键字的局部变量声明 VS 'as' 关键字的性能差异
local variable declaration with 'is' keyword VS 'as' keyword performance difference
object obj = "Hello";
// is keyword
if (obj is string str1)
{
Console.WriteLine(str1);
}
// as keyword
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
在上面的代码中,局部变量是用'is'关键字声明的,但是用'as'关键字在性能上有什么区别吗?
我想知道是否存在与转换和空值检查相关的性能差异。 (除了 str1 和 str2 变量的局部范围差异)
这段代码更好:
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
CLR 检查一次,而第一个检查两次,第一次使用 IS 运算符,然后进行类型转换,这显然是一种开销。
两个代码示例绝对100%相同;我们可以通过查看 IL 来测试这一点,这可以通过多种方式完成,但最方便的是 https://sharplab.io/
考虑:
using System;
public class C {
object obj = "Hello";
public void ViaIsWithCapture()
{
// is keyword
if (obj is string str1)
{
Console.WriteLine(str1);
}
}
public void ViaAsThenNullTest()
{
// as keyword
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
}
}
我们可以 运行 通过 sharplab.io like this,如果你看右边,两个版本的 IL 相同:
.method public hidebysig
instance void ViaIsWithCapture () cil managed
{
// Method begins at RVA 0x2050
// Code size 22 (0x16)
.maxstack 1
.locals init (
[0] string str1
)
IL_0000: ldarg.0
IL_0001: ldfld object C::obj
IL_0006: isinst [System.Private.CoreLib]System.String
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.0
IL_0010: call void [System.Console]System.Console::WriteLine(string)
IL_0015: ret
} // end of method C::ViaIsWithCapture
对
.method public hidebysig
instance void ViaAsThenNullTest () cil managed
{
// Method begins at RVA 0x2074
// Code size 22 (0x16)
.maxstack 1
.locals init (
[0] string str2
)
IL_0000: ldarg.0
IL_0001: ldfld object C::obj
IL_0006: isinst [System.Private.CoreLib]System.String
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.0
IL_0010: call void [System.Console]System.Console::WriteLine(string)
IL_0015: ret
} // end of method C::ViaAsThenNullTest
object obj = "Hello";
// is keyword
if (obj is string str1)
{
Console.WriteLine(str1);
}
// as keyword
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
在上面的代码中,局部变量是用'is'关键字声明的,但是用'as'关键字在性能上有什么区别吗?
我想知道是否存在与转换和空值检查相关的性能差异。 (除了 str1 和 str2 变量的局部范围差异)
这段代码更好:
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
CLR 检查一次,而第一个检查两次,第一次使用 IS 运算符,然后进行类型转换,这显然是一种开销。
两个代码示例绝对100%相同;我们可以通过查看 IL 来测试这一点,这可以通过多种方式完成,但最方便的是 https://sharplab.io/
考虑:
using System;
public class C {
object obj = "Hello";
public void ViaIsWithCapture()
{
// is keyword
if (obj is string str1)
{
Console.WriteLine(str1);
}
}
public void ViaAsThenNullTest()
{
// as keyword
string str2 = obj as string;
if (str2 != null)
{
Console.WriteLine(str2);
}
}
}
我们可以 运行 通过 sharplab.io like this,如果你看右边,两个版本的 IL 相同:
.method public hidebysig
instance void ViaIsWithCapture () cil managed
{
// Method begins at RVA 0x2050
// Code size 22 (0x16)
.maxstack 1
.locals init (
[0] string str1
)
IL_0000: ldarg.0
IL_0001: ldfld object C::obj
IL_0006: isinst [System.Private.CoreLib]System.String
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.0
IL_0010: call void [System.Console]System.Console::WriteLine(string)
IL_0015: ret
} // end of method C::ViaIsWithCapture
对
.method public hidebysig
instance void ViaAsThenNullTest () cil managed
{
// Method begins at RVA 0x2074
// Code size 22 (0x16)
.maxstack 1
.locals init (
[0] string str2
)
IL_0000: ldarg.0
IL_0001: ldfld object C::obj
IL_0006: isinst [System.Private.CoreLib]System.String
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.0
IL_0010: call void [System.Console]System.Console::WriteLine(string)
IL_0015: ret
} // end of method C::ViaAsThenNullTest