某些数据的副本不属于堆(没有特殊处理。)例如,堆栈上的JavaScriptValue结构在与Chakra JavaScript引擎互操作方面做得很好。
但据我了解,在托管堆上存储这样的值(没有正确的引用计数)会导致可能的悬空引用。有没有办法将这样的c#结构声明为 non-boxable ?
澄清,如果在类型上生成任何装箱操作,我希望c#编译器生成错误消息。
参考:请参阅MSDN JSAddRef reference,其中包含:
这只需要在 不会存储的JsRef句柄上调用 在堆栈的某个地方。 调用JsAddRef可确保JsRef引用的对象> 在调用JsRelease之前不会被释放。
我从中收集到Chakra可能正在使用“保守的垃圾收集”方法,使得JsAddRef / JsRelease不需要基于堆栈的JsRef句柄。我想用来使用类(不是结构) )将JsRef句柄包装在堆上,并进行转换操作以调用JsAddRef,并使用IDisposable模式调用JsRelease。
答案 0 :(得分:1)
对于 C# 7.2+,答案是肯定的:只需在结构 placefields = np.reshape(placefields,(len(placefields),99,1))
nspikes = np.swapaxes(np.tile(spikes, (xybins,1,1)),0,1)
probability = np.empty((len(spikes[0]), xybins))
chunks = len(spikes[0])//20
n = int(len(spikes[0])/chunks)
for i in range(0,len(nspikes[0][0]),n):
nspikes_chunk = nspikes[:,:,i:i+n]
probability_chunk = stats.poisson.pmf(nspikes_chunk,placefields)
probability_chunk = np.swapaxes(probability_chunk.prod(axis=0),0,1)
if len(probability_chunk)<(len(spikes)//chunks):
probability[i:] = probability_chunk
else:
probability[i:i+len(probability_chunk)] = probability_chunk
上使用 ref 关键字。只允许在堆栈上,而不是在堆上(因此不能对其进行装箱)。
请参阅此处了解更多信息:http://www.devsanon.com/c/c-7-2-introducing-ref-struct/
这里: https://docs.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code#use-ref-struct-types
答案 1 :(得分:0)
它被装箱,因为你将它存储在堆上的数据结构中。
你将它包装在非值类型中。
围绕这个主题有很多问题。如果你不想读一本书,那么你应该阅读所有这些。其中一些很有趣。
所以没有不可能创建一个非盒式结构 - 因为你做了什么,它会被装箱。
答案 2 :(得分:0)
CLI ECMA-335 specification说(第I.8.2.4节):
所有值类型都有一个名为
box
的操作。装箱任何值类型的值会产生其盒装值;即,包含该按位副本的相应盒装类型的值 原始价值。
还有一些额外的语言说明Nullable<T>
会发生什么(包含的值被装箱或产生空引用),并且无法对托管指针执行框操作,但没有提及任何异常对于价值类型。
答案 3 :(得分:0)
正如其他人所写的那样,值类型将被装箱(您可以将其视为包含在引用类型中)以便能够进入堆中。
但更重要的是,这与悬挂引用和引用计数无关。无论存放在哪里都无关紧要。
我相信你所问的是如何管理原生资源,这是另一回事。如果从.NET世界之外的某些东西分配资源,通常需要确保在完成后释放/释放它。通常,您将其包装在一个实现IDisposable
的类中,并手动(或在析构函数中)处理它。现在,如果你忘了处理你应该做的事情,或者保留对已经处置的东西的引用,你就会遇到麻烦。但这一切都取决于资源是什么。
对于JavaScriptValue
的特定情况,我真的不知道它是如何工作的。虽然在我看来,如果那里的IntPtr引用了需要处理的东西,JavaScriptValue
将是一个实现IDisposable而不是结构的类。存储需要在结构中处理的内容将是一种非常好的陷入困境的方法,因为您可能会在整个地方都有该引用的副本。所以我假设你不需要打扰 - 但你应该检查文档以确定。