代码之家  ›  专栏  ›  技术社区  ›  Øyvind Bråthen

强制转换使用是两次,或者使用as one并创建一个新变量

  •  6
  • Øyvind Bråthen  · 技术社区  · 15 年前

    在今天的前一个问题中,这两种不同的方法被用来回答一个问题。

    我们有一个对象可能实现,也可能不实现 IDisposable . 如果是的话,我们想处理它,如果不是,我们什么也不做。这两种不同的方法是:

    1)

    if(toDispose is IDisposable)
      (toDispose as IDisposable).Dispose();
    

    2)

    IDisposable disposable = toDispose as IDisposable;
    if( disposable != null )
      disposable.Dispose();
    

    主要是,从评论中可以看出,共识是2)是最好的方法。

    但看看这些差异,我们可以得出以下结论:

    1)在显示上执行两次投射。

    2)只执行一次强制转换,但创建一个新的中间对象。

    我想2会稍微慢一点,因为它必须分配一个新的局部变量,所以为什么在这种情况下,这是最好的解决方案?仅仅是因为可读性问题?

    6 回复  |  直到 13 年前
        1
  •  12
  •   Jon Skeet    15 年前

    我的经验法则是:

    • 如果它是一个错误/错误值 要想成为合适的类型,只需铸造
    • 否则使用 as 就像你的第二个案子一样
    • 如果处理的是值类型,则可以使用 作为 具有可为空的类型(用于一致性)或使用 is 和一个直接演员

    注意你的第二张表格 创建一个“新中间对象”。它创建了一个新的中间 变量 . 你的第一个方法真的是这样的吗?它只是让编译器有效地隐藏了变量。它仍然作为堆栈位置存在于IL中,但在源代码中没有任何表示。

    说了这么多,在 这个案子 (你只想处理的地方),我相信达林的方法是最好的。

        2
  •  13
  •   Darin Dimitrov    15 年前

    不是真的回答你的问题,但我建议你这样做:

    using (toDispose as IDisposable)
    {
        ...
    }
    

    让编译器担心 ifs , finally Dispose 电话。

        3
  •  4
  •   Andreas Paulsson    15 年前

    它被认为是一个更好的解决方案,因为变量分配被认为比强制转换更快。此外,编译器可以很好地优化强制转换。

    不管怎样,这都是微观优化。 使用您认为最容易维护的代码。

        4
  •  2
  •   Guffa    15 年前

    第二种选择实际上更快。与访问本地变量相比,执行额外的强制转换需要更多的时间。

    分配局部变量并不慢。其实根本不需要时间。

    当输入一个方法时,通过向下移动堆栈指针为该方法中的本地数据分配空间来创建堆栈帧。从堆栈指针中减去一个更大的数字不需要花费更多的时间,因此为局部变量分配空间完全不需要花费时间。这不是几乎没有时间,而是实际上零时间。

    局部变量的唯一开销是使用堆栈空间,但是由于它只占一兆字节(IIRC)堆栈的几个字节,所以除非进行深层递归调用,否则没有问题。

    另外,如果需要的话,编译器可以自己创建局部变量,因此两种方法最终都可能使用局部变量。

        5
  •  1
  •   Nope landerton    15 年前

    在这里使用反射工作还是要比使用慢 as ?

    我创建了两个类,一个名为 ICanDispose 实现 IDisposable 还有一个叫 ICanNotDispose 不执行 可识别 .

    在我的 icandose公司 类I只显示一个消息框来检查反射是否实际调用了 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);
        }
    }
    
        6
  •  1
  •   akjoshi HCP    13 年前

    这里没有人提到fxcop显示 DoNotCastUnnecessarily 第一次批准时发出警告。此规则的帮助建议用第二种方法代替第一种方法

    http://msdn.microsoft.com/en-us/library/ms182271(VS.90).aspx

    重复的强制转换会降低性能, 尤其是当演员 在紧凑迭代中执行 声明。用于显式复制 强制转换操作,存储 在局部变量中强制转换并使用 局部变量而不是 重复的强制转换操作。

    如果使用C IS操作员进行测试 演员阵容是否会成功 进行实际的铸造,考虑 测试AS操作员的结果 相反。这提供了相同的 无隐式功能 由IS执行的强制转换操作 操作员。