所有C#强制转换都会导致装箱/取消装箱

时间:2012-02-20 18:15:46

标签: c# .net clr boxing

我很想知道C#中的所有演员阵容是否会导致拳击,如果不是,所有演员阵容都是一次代价高昂的操作?

取自Boxing and Unboxing (C# Programming Guide)

的示例
    int i = 123;
    // The following line boxes i.
    object o = i;  

这一行显然导致装箱(将int类型包装为一个对象)。 这是一项被认为代价高昂的操作,因为它会产生将要收集的垃圾。

来自2种不同类型的参考类型的演员表怎么样?那是多少钱?可以正确测量吗? (与前一个例子相比)

例如:

public class A
{
}

public class B : A
{
}

var obj = new B();
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing

3 个答案:

答案 0 :(得分:23)

  

我很想知道C#中的所有转换是否都会导致拳击。

没有。只有拳击转换导致拳击,因此名称“拳击转换”。 Boxing转换是从值类型到引用类型的所有内置转换 - 要么是值类型继承的类,要么是它实现的接口。 (或通过协变或逆变参考转换,与其实现的接口兼容的接口。)

  

所有转换都是一项代价高昂的操作吗?

没有。身份转换是零成本,因为编译器可以完全忽略它们。

  

隐式和显式引用转换的成本是多少?

隐式参考转化为零成本。编译器可以完全忽略它们。也就是说,从Giraffe转换为其基本类型Animal,或Giraffe转换为其实现的接口类型IAmATallMammal,是免费的。

显式引用转换涉及运行时检查,以验证引用确实引用了所需类型的对象。

运行时检查是否“代价高昂”取决于您的预算。

  

可以正确衡量成本吗?

不确定。决定哪些资源与您相关 - 比如说时间 - 然后用秒表仔细衡量您的时间消耗。

你没有提出但可能应该提出的问题:

  

哪些转化费用最高?

用户定义的转换只不过是方法调用的语法糖;这个方法可以任意长,就像任何方法一样。

动态转换在运行时再次启动编译器;编译器可能会花费任意长的时间来执行类型分析,具体取决于您选择分析问题的难度。

答案 1 :(得分:10)

没有

装箱意味着将值放入新的引用类型实例。

引用类型之间的标准强制转换不会导致任何分配 (用户定义的强制转换可以做任何事情)

答案 2 :(得分:7)

  

我很想知道C#中的所有演员是否会导致拳击,

没有。 Boxing是very special operation,意味着将值类型的实例视为引用类型的实例。对于参考类型转换为引用类型转换,该概念不起作用。

  

所有演员都是一次代价高昂的演出?

简短回答:不。

答案很长:定义昂贵。但仍然没有。

  

来自2种不同类型的参考类型的演员表怎么样?那是多少钱?

那么,如果它只是派生到基准引用转换怎么办?那是快速的,因为没有任何反应。

其他用户定义的转换可能“慢”,它们可能“快速”。

这个“慢”。

class A { public int Foo { get; set; } }
class B {
    public int Foo { get; set; }
    static Random rg = new Random();
    static explicit operator A(B b) {
        Thread.Sleep(rg.Next());
        return new A { Foo = b.Foo; }
    }
}

这个是“快”。

class A { public int Foo { get; set; } }
class B {
    public int Foo { get; set; }
    static Random rg = new Random();
    static explicit operator A(B b) {
        return new A { Foo = b.Foo; }
    }
}
  

var obj2 = (A)obj; //这是一项“昂贵”的操作吗?这不是拳击

不,这是“便宜的”。