是否有可能在c#中创建一个不可框的结构体?

本文关键字:一个 结构体 有可能 创建 是否 | 更新日期: 2023-09-27 18:12:44

一些数据的副本不属于堆(没有特殊处理)。例如,堆栈上的JavaScriptValue结构体在与Chakra JavaScript引擎的互操作方面做得很好。

但是据我所知,在托管堆上存储这样的值(没有适当的引用计数)会导致可能的悬垂引用。有没有一种方法可以将c#结构声明为non-boxable?

说明,我希望c#编译器在该类型上生成任何装箱操作时生成错误消息。

参考:参见MSDN JSAddRef参考,其中说:

这只需要在不被存储的JsRef句柄上调用在堆栈的某个地方。调用JsAddRef确保JsRef引用的对象>直到调用JsRelease才释放。

我从中推断Chakra可能使用了"保守的垃圾收集"方法,使得JsAddRef/JsRelease对于基于堆栈的JsRef句柄来说是不必要的。我想使用一个类(不是结构)来包装堆上的JsRef句柄,并有一个转换操作来调用JsAddRef,并使用IDisposable模式来调用JsRelease。

是否有可能在c#中创建一个不可框的结构体?

对于c# 7.2+,答案是肯定的:只需在结构体ref struct上使用ref关键字。它将只允许在堆栈上,而不允许在堆上(因此不能在它上进行装箱)。

查看更多信息:http://www.devsanon.com/c/c-7-2-introducing-ref-struct/

这里:https://learn.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code use-ref-struct-types

CLI ECMA-335规范规定(章节I.8.2.4):

所有的值类型都有一个叫做box的操作。装箱任何值类型的值都会产生其装箱值;即,对应的盒装类型的值,其中包含对象的按位副本原始值。

有一些额外的语言说明Nullable<T>发生了什么(包含的值被框起来或产生一个空引用),框操作不能在托管指针上执行,但没有提到值类型的任何异常。

它被装箱是因为您将它存储在堆上的数据结构中。

把它包装在一个非值类型中。

关于这个话题有很多问题。如果你不想读一本书,那么你应该读所有这些书。其中一些很有趣。

所以,不,我们不可能创建一个非boxable结构体——它会因为你所做的而被装箱

就像其他人写的那样,值类型将被装箱(你可以把它想象成它们被包装在引用类型中),以便能够进入堆。

但更重要的是,这与悬空引用和引用计数无关。不管它存储在哪里

我相信你问的是如何管理本地资源,那是另一回事。如果你从。net世界之外的地方分配资源,你通常需要确保你在使用它的时候释放它。通常,您将其封装在实现IDisposable的类中,并手动(或在析构函数中)处理它。现在,如果你忘记处理你应该处理的东西,或者保留对已经处理的东西的引用,你就会陷入麻烦。但所有这些都取决于资源是什么。

对于JavaScriptValue的具体情况,我真的不知道这是如何工作的。虽然在我看来,如果那里的IntPtr引用了需要处理的东西,JavaScriptValue将是一个实现IDisposable的类,而不是一个结构体。将需要在结构体中处理的东西存储在一个结构体中会很容易陷入麻烦,因为你可能在任何地方都有该引用的副本。所以我想假设您不需要麻烦 -但是您应该检查文档以确保。