所有 C# 转换都会导致装箱/拆箱吗

发布于 2025-01-07 13:16:34 字数 573 浏览 0 评论 0原文

我很想知道 C# 中的所有强制转换是否都会导致装箱,如果不是,那么所有强制转换都是成​​本高昂的操作吗?

示例取自 装箱和拆箱(C# 编程指南)

    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

I am curious to know if all casts in C# result in boxing, and if not, are all casts a costly operation?

Example taken from Boxing and Unboxing (C# Programming Guide)

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

This line obviously causes boxing (wrapping up the int type as an object).
This is an operation that is considered costly, since it creates garbage that will be collected.

What about casts from 2 different types of reference types? what is the cost of that? can it be properly measured? (compared to the previous example)

For example:

public class A
{
}

public class B : A
{
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枯寂 2025-01-14 13:16:34

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

不会。只有装箱转换才会产生装箱,因此称为“装箱转换”。装箱转换都是从值类型到引用类型的内置转换——要么是值类型继承的类,要么是它实现的接口。 (或者通过协变或逆变引用转换到与其实现的接口兼容的接口。)

所有转化都是成本高昂的操作吗?

不会。标识转换的成本为零,因为编译器可以完全消除它们。

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

隐式引用转换是零成本。编译器可以完全消除它们。也就是说,从 Giraffe 转换为其基本类型 Animal,或者从 Giraffe 转换为其实现的接口类型 IAmATallMammal,都是免费的。

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

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

这个成本可以正确衡量吗?

当然。确定哪些资源与您相关(例如时间),然后用秒表仔细测量您的时间消耗。

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

最昂贵的转化是什么?

用户定义的转换只不过是方法调用的语法糖;与任何方法一样,该方法可能需要任意长的时间。

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

I am curious to know if all conversions in C# result in boxing.

No. Only boxing conversions result in boxing, hence the name "boxing conversions". Boxing conversions are all built-in conversions from value types to reference types -- either to a class that the value type inherits from, or to an interface that it implements. (Or to an interface compatible with an interface it implements, via a covariant or contravariant reference conversion.)

are all conversions a costly operation?

No. Identity conversions are zero cost because the compiler can elide them entirely.

What are the costs of implicit and explicit reference conversions?

Implicit reference conversions are zero cost. The compiler can elide them entirely. That is, converting from Giraffe to its base type Animal, or Giraffe to its implemented interface type IAmATallMammal, are free.

Explicit reference conversions involve a runtime check to verify that the reference does in fact refer to an object of the desired type.

Whether that runtime check is "costly" or not depends on your budget.

can that cost be properly measured?

Sure. Decide what resource is relevant to you -- time, say -- and then carefully measure your consumption of time with a stopwatch.

A question you did not ask but probably should have:

What are the most expensive conversions?

User-defined conversions are nothing more than a syntactic sugar for a method call; that method can take arbitrarily long, like any method.

Dynamic conversions start the compiler again at runtime; the compiler may take arbitrarily long to perform a type analysis, depending on how hard an analysis problem you choose to throw at it.

酒儿 2025-01-14 13:16:34

不。

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

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

No.

Boxing means putting a value into a new reference type instance.

Standard casts between reference types do not result in any allocations.
(User-defined casts can do anything)

小…楫夜泊 2025-01-14 13:16:34

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

不会。装箱是一种非常特殊的操作,这意味着处理值类型的实例作为引用类型的实例。对于引用类型转换到引用类型转换,该概念不起作用。

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

简短回答:不。

详细回答:定义成本高昂。但仍然没有。

来自 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; // 这是一个“昂贵”的操作吗?这不是拳击

,不,这是“便宜”。

I am curious to know if all casts in C# result in boxing,

No. Boxing is a very special operation that means treating an instance of a value type as an instance of a reference type. For reference type conversion to reference type conversion, the concept plays no role.

are all casts a costly operation?

Short answer: No.

Long answer: Define costly. Still no, though.

What about casts from 2 different types of reference types? what is the cost of that?

Well, what if it's just a derived to base reference conversion? That's BLAZINGLY fast because nothing happens.

Other, user-defined conversions, could be "slow", they could be "fast."

This one is "slow."

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; }
    }
}

This one is "fast."

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; // is this an "expensive" operation? this is not boxing

No, it's "cheap."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文