英文:
What should be the C# equivalent of Rust's Box<> type?
问题
Rust中有一种叫做 Box<>
的类型,据说它是C++中智能指针的等价物。
C#中应该使用什么类型来等效于Rust的 Box<>
类型?
英文:
I am translating Rust code into C#.
Rust has some type called Box<>
which is said to be C++'s equivalent of smart pointers.
What should be the C# equivalent of Rust's Box<>
type?
答案1
得分: 4
答案很简短,没有一个完全等同的类型。
Box
用于将值存储在堆上。有许多原因可以使用它,但这就是它的全部作用。
在 C# 中,引用类型始终指向堆分配。因此,在引用类型上进行"装箱"是没有意义的,因为它们已经被有效地装箱了。
相反,C# 值类型直接分配,可以分配在堆栈上,或者如果作为非静态类字段使用,则直接分配在对象的堆分配内部。您可以通过将其强制转换为兼容的引用类型(object
或值类型实现的接口类型)来装箱 C# 值类型。
但是,C# 中的引用类型不仅被装箱,还具有共享所有权以及共享可变性,并且因此 C# 引用类型更接近于实现这些行为的 Rust 类型,例如 Rc<RefCell<T>>
或 Arc<Mutex<T>>
,尽管这些类型和 C# 引用类型之间仍然存在非常重要的语义差异(Rc<_>
不能发送到其他线程,Arc<Mutex<_>>
必须锁定才能访问内部值,Rc
和 Arc
都可以创建引用循环,可能导致内存泄漏等)。特别是共享可变性需要某种同步/原子性才能通过 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<RefCell<T>>
or Arc<Mutex<T>>
, though there are still very relevant semantic differences between those types and C# reference types (Rc<_>
can't be sent to other threads, Arc<Mutex<_>>
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<dyn _>
)? 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<T>(T val) {
public T _val = val;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论