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

lys*_*cid 11 .net c# clr boxing

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

拳击和拆箱中获取的示例(C#编程指南)

    int i = 123;
    // The following line boxes i.
    object o = i;  
Run Code Online (Sandbox Code Playgroud)

这一行显然导致装箱(将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
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 24

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

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

所有转换都是昂贵的操作吗?

不会.身份转换是零成本,因为编译器可以完全忽略它们.

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

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

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

运行时检查是否"昂贵"取决于您的预算.

能够正确衡量成本吗?

当然.确定哪些资源与您相关 - 比如说时间 - 然后用秒表仔细测量您的时间消耗.

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

什么是最昂贵的转换?

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

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

  • @phoog:正确.没有必要为此生成IL; 字符串引用已与变量赋值兼容. (2认同)

SLa*_*aks 10

没有.

拳击意味着将值放入新的引用类型实例中.

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


jas*_*son 7

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

不是.Boxing是一种非常特殊的操作,意味着将值类型的实例视为引用类型的实例.对于参考类型转换为引用类型转换,该概念不起作用.

所有演员都付出了昂贵的代价?

简答:不.

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

那些来自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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个"快".

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

不,它"便宜".