在今天的上一个问题中,这两种不同的方法被作为答案提出问题。
我们有一个可能会或可能不会实现IDisposable
的对象。如果是的话,我们想要处理它,如果不是我们什么也不做。这两种不同的方法是:
1)
if(toDispose is IDisposable)
(toDispose as IDisposable).Dispose();
2)
IDisposable disposable = toDispose as IDisposable;
if( disposable != null )
disposable.Dispose();
主要是,从评论中可以看出,共识是2)是最好的方法。
但是看看差异,我们归结为:
1)在toDispose上执行两次演员。
2)仅执行一次转换,但创建一个新的中间对象。
我猜测2会慢一点因为它必须分配一个新的局部变量,所以为什么这被认为是这种情况下的最佳解决方案?这完全是因为可读性问题?
答案 0 :(得分:13)
没有真正回答你的问题,但我建议你这个结构:
using (toDispose as IDisposable)
{
...
}
让编译器担心ifs
,finally
和Dispose
来电。
答案 1 :(得分:12)
关于施法的经验法则:
as
,就像第二种情况一样as
与可空类型一起使用(为了保持一致性),或者使用is
和直接投射请注意,您的第二个表单不会创建“新的中间对象”。它创建了一个新的中间变量。那么你的第一种方法是否真的 - 只是变量被编译器有效地隐藏了。它仍然作为堆栈位置存在于IL中,但它在源代码中没有任何表示。
说完所有这些,在这个特殊情况下(你只想处理),Darin的方法是最好的,我相信。
答案 2 :(得分:4)
它被认为是一种更好的解决方案,因为变量分配被认为比强制转换更快。此外,演员可以通过编译器对其进行优化。
无论哪种方式,无论如何这都是微优化的。 使用您认为最容易维护的代码。
答案 3 :(得分:2)
第二种选择实际上有点快。进行额外演员需要花费更多时间而不是访问本地变速器。
分配局部变量并不慢。实际上它根本没有时间。
当输入方法时,通过向下移动堆栈指针来创建堆栈帧,以便为方法中的本地数据分配空间。从堆栈指针中减去更大的数字不需要更长的时间,因此根本不需要时间为局部变量分配空间。这几乎没有时间,但实际上是零时间。
局部变量的唯一成本是你正在使用堆栈空间,但由于它只有一兆字节(IIRC)堆栈中的几个字节,所以除非你正在进行深度递归调用,否则没有问题。
此外,如果需要,编译器可以自己创建局部变量,因此两种方法最终都可能最终使用局部变量。
答案 4 :(得分:1)
与使用as
?
我创建了两个类,一个名为ICanDispose
,实现了IDisposable
,另一个名为ICanNotDispose
,未实现IDisposable
。
在我的ICanDispose
课程中,我只是显示一个消息框,以检查反射实际上是否调用了Dispose
方法。
我的表单上有一个按钮,执行下面的代码。使用反射它会检查我的对象是否实现IDisposable
接口,如果是,则调用Dispose
方法。
private void button1_Click(object sender, EventArgs e)
{
ICanDispose myObject1 = new ICanDispose();
ICanNotDispose myObject2 = new ICanNotDispose();
// Checking object 1 which does implement IDisposable.
if (myObject1.GetType().GetInterface("IDisposable", true) != null)
{
myObject1.GetType().InvokeMember(
"Dispose",
System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod,
null,
Activator.CreateInstance(myObject1.GetType()),
null);
}
// Checking object 2 which does not implement IDisposable.
if (myObject2.GetType().GetInterface("IDisposable", true) != null)
{
myObject2.GetType().InvokeMember(
"Dispose",
System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod,
null,
Activator.CreateInstance(myObject2.GetType()),
null);
}
}
答案 5 :(得分:1)
此处没有人提到FxCop在第一次approch时显示DoNotCastUnnecessarily
警告。对此规则的帮助表明第二种方法取代了第一种方法
http://msdn.microsoft.com/en-us/library/ms182271(VS.90).aspx
重复演员表会降低演奏效果, 特别是当演员表演时 在紧凑的迭代中执行 声明。对于显式重复 转换操作,存储结果 转换为局部变量并使用 局部变量而不是 重复演员。
如果C#是运算符用于测试 演员是否会成功 考虑到实际演员阵容 测试as运算符的结果 代替。这提供了相同的 没有隐含的功能 施法操作是由 操作