C#中等价于Rust的`Box<>`类型应该是什么?

huangapple go评论71阅读模式
英文:

What should be the C# equivalent of Rust's Box<> type?

问题

Rust中有一种叫做 Box&lt;&gt; 的类型,据说它是C++中智能指针的等价物。

C#中应该使用什么类型来等效于Rust的 Box&lt;&gt; 类型?

英文:

I am translating Rust code into C#.

Rust has some type called Box&lt;&gt; which is said to be C++'s equivalent of smart pointers.

What should be the C# equivalent of Rust's Box&lt;&gt; type?

答案1

得分: 4

答案很简短,没有一个完全等同的类型。

Box 用于将值存储在堆上。有许多原因可以使用它,但这就是它的全部作用。

在 C# 中,引用类型始终指向堆分配。因此,在引用类型上进行"装箱"是没有意义的,因为它们已经被有效地装箱了。

相反,C# 值类型直接分配,可以分配在堆栈上,或者如果作为非静态类字段使用,则直接分配在对象的堆分配内部。您可以通过将其强制转换为兼容的引用类型(object 或值类型实现的接口类型)来装箱 C# 值类型。

但是,C# 中的引用类型不仅被装箱,还具有共享所有权以及共享可变性,并且因此 C# 引用类型更接近于实现这些行为的 Rust 类型,例如 Rc<RefCell<T>>Arc<Mutex<T>>,尽管这些类型和 C# 引用类型之间仍然存在非常重要的语义差异(Rc<_> 不能发送到其他线程,Arc<Mutex<_>> 必须锁定才能访问内部值,RcArc 都可以创建引用循环,可能导致内存泄漏等)。特别是共享可变性需要某种同步/原子性才能通过 Rust 编译器,而在 C# 中,您可以轻松创建数据竞争而没有问题。

换句话说,您需要看看值为什么被装箱。

  • 是否是为了在一组异构值上启用多态性(Box<dyn _>)?只需使用 C# 接口。
  • 是否是为了启用递归结构?只需使用 C# 类,它们可以自我递归而没有问题。
英文:

The short answer is that there isn't an exactly-equivalent type.

Box is used to put a value on the heap. There are several reasons why you would want to do that, but that's all it does.

In C#, reference types always point to a heap allocation. "Boxing" is therefore pointless on reference types, as they are already effectively boxed.

C# value types are instead allocated directly, either on the stack or directly inside an object's heap allocation if used as a non-static class field. You can box a C# value type by casting it to a compatible reference type: either object or an interface type implemented by the value type.

However, reference types in C# are not just boxed, they also have shared ownership as well as shared mutability and so C# reference types are closer to the Rust types that implement those behaviors, such as Rc&lt;RefCell&lt;T&gt;&gt; or Arc&lt;Mutex&lt;T&gt;&gt;, though there are still very relevant semantic differences between those types and C# reference types (Rc&lt;_&gt; can't be sent to other threads, Arc&lt;Mutex&lt;_&gt;&gt; has to be locked to access the inner value, both Rc and Arc can create reference cycles that could cause a memory leak, etc.). Shared mutability in particular requires some kind of synchronization/atomicity to even pass the Rust compiler, where C# has no problem letting you create data races.


In other words, you need to look at why the value is boxed.

  • Is it to enable polymorphism on a set of heterogeneous values (Box&lt;dyn _&gt;)? Just use C# interfaces.
  • Is it to enable a recursive structure? Just use C# classes, which can self-recurse without issue.

答案2

得分: -1

public class Box<T>(T val) {
    public T _val = val;
}
英文:
public class Box&lt;T&gt;(T val) {
    public T _val = val;
}

huangapple
  • 本文由 发表于 2023年6月2日 02:34:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384759.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定