我正在查看具有此模式的函数:
if( obj is SpecificClass1 )
{
((SpecificClass1)obj).SomeMethod1();
}
else if( obj is SpecificClass2 )
{
((SpecificClass2)obj).SomeMethod2();
}
else if( obj is SpecificClass3 )
{
((SpecificClass3)obj).SomeMethod3();
}
并获取代码性能分析警告:CA1800 不必要地强制转换。
为什么双转换(在 if 表达式中使用"is"运算符,在每个 if 的主体中使用括号样式转换)没有被编译器优化掉。我不明白为什么这将是编译器无法解决的性能问题。
简单地说,编译器希望你改变:
if( obj is SpecificClass1 )
{
((SpecificClass1)obj).SomeMethod1();
}
自
SpecificClass1 Class1Obj = obj as SpecificClass1;
if (Class1Obj != null)
{
Class1Obj.SomeMethod1();
}
是的,可以想象编译器可以为您进行转换。但是,我猜编译器团队决定编译器最好发出警告,并要求您进行更改。
想象一下,如果你的原始代码读到:
if( obj is SpecificClass1 )
{
((SpecificClass1)obj).SomeMethod1();
((SpecificClass1)obj).SomeMethod2();
((SpecificClass1)obj).SomeMethod3();
}
在这一点上,我认为您可以同意,纯粹为了清楚起见,最好由程序员修改代码。在这一点上,如果代码以另一种方式编写得更好,恰好更有效、更清晰,那么实施优化的意义何在?
经过一番搜索:答案在警告描述中。
我是对的,在这种情况下,编译器正在寻找as
表达式,这将使您免于两个强制转换(is
和()
转换):
Derived d = new Derived();
Base b = d as Base;
if (b != null)
{
Console.WriteLine(b.ToString());
}
您实际上是在执行两个转换,因为is
也在执行转换类型的操作。
优化编译器可以省略第二个强制转换,但这不是必需的,并且 C# 内存模型可能会阻止在许多常见情况下应用此优化。如果始终将首选形式与 as
运算符一起使用,则无论编译器是否实现特殊逻辑来检测和优化这些情况,您都可以获得此"优化"的好处。
引用Eric Lippert(曾经在C#团队工作):
我一直被问到"为什么C#不实现功能X?"。答案总是相同的:因为没有人设计、指定、实现、测试、记录和交付该功能。所有这六件事都是实现功能所必需的。所有这些都花费了大量的时间、精力和金钱。功能并不便宜,我们非常努力地确保我们只提供那些在时间、精力和金钱预算有限的情况下为用户提供最大利益的功能。