在 .NET 中,如果将结构传递到带有接口参数的方法中,它是否会将值装箱?

发布于 2024-10-23 18:42:45 字数 421 浏览 0 评论 0原文

从一个简单的测试中我可以看到,如果您将结构传递到方法中,它会按值传递,但如果您首先将它分配给接口,它会按引用传递。

interface IFoo { int Val { get; set; } }
struct Foo : IFoo { public int Val { get; set; } }

void Bar(IFoo foo) { foo.Val = 1; }

Foo foo = new Foo();
IFoo ifoo = new Foo();

Bar(foo);
Bar(ifoo);

Console.WriteLine(foo.Val);  // 0, passed by value
Console.WriteLine(ifoo.Val); // 1, passed by ref

所以我的问题是,是否还有像这样传递结构的装箱操作?

From a simple test I can see that if you pass the struct into the method it is passed by value but if you first assign it to an interface it is passed by reference.

interface IFoo { int Val { get; set; } }
struct Foo : IFoo { public int Val { get; set; } }

void Bar(IFoo foo) { foo.Val = 1; }

Foo foo = new Foo();
IFoo ifoo = new Foo();

Bar(foo);
Bar(ifoo);

Console.WriteLine(foo.Val);  // 0, passed by value
Console.WriteLine(ifoo.Val); // 1, passed by ref

So my question is, is there still a boxing operation for passing a struct in like this?

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

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

发布评论

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

评论(2

沉溺在你眼里的海 2024-10-30 18:42:45

每当结构体转换为接口时,它就会被装箱。

Foo foo = new Foo();//Doesn't box yet
IFoo ifoo = new Foo();//Boxes

Bar(foo);//creates a new boxed copy
Bar(ifoo);//Uses the old boxed version created in line 2

您可以通过使用接口作为约束使参数泛型来避免装箱:

void Bar<T>(T foo)
    where T:IFoo 
{
}

这利用了泛型针对每个值类型进行专门化的事实。


但是,如果您遵循可变结构是邪恶的设计准则,从而使您的结构不可变,那么代码框与否并不重要。装箱只会对性能造成轻微影响,但不会对语义产生太大影响。

Whenever a struct gets converted to an interface it gets boxed.

Foo foo = new Foo();//Doesn't box yet
IFoo ifoo = new Foo();//Boxes

Bar(foo);//creates a new boxed copy
Bar(ifoo);//Uses the old boxed version created in line 2

You can avoid that boxing by making the parameter generic using the interface as a constraint:

void Bar<T>(T foo)
    where T:IFoo 
{
}

This uses the fact that generics get specialized for every value type.


But if you follow the design guideline that mutable strucs are evil, and thus make your struct immutable, it doesn't matter much if the code boxes or not. The boxing then only causes a slight performance hit, but doesn't change semantics much.

鹤舞 2024-10-30 18:42:45

接口都是引用类型,因此装箱发生在线路上,

IFoo ifoo = new Foo();

而不是调用 Bar 时。

Interfaces are all reference types, so the boxing occurs on the line

IFoo ifoo = new Foo();

rather than when calling Bar.

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