禁止复制变量

  • 本文关键字:变量 复制 禁止 c#
  • 更新时间 :
  • 英文 :


我有一个类Foo,它包含一个指针,从C dll非托管内存。它实现了IDisposable使用C dll释放非托管内存,并使用dll实现了一些其他功能。

public unsafe class Foo : IDisposable {
void* ptr;
internal Foo() { 
/* initialize ptr from C dll */
};
public int getInfo() {
/* return info from ptr using dll */
}
public Dispose() {
/* free ptr using C dll */
}
}

我也有一个工厂返回Foo对象的范例:

public unsafe class FooFactory {
public Foo createFoo() {
return new Foo();
}
}

最后我有一个函数,它接受Foo作为参数,处理它并返回:

public Foo process(Foo f) {
/* do some stuff with f */
return f;
}

所有我想做的是防止用户创建Foo对象,将其存储在一个变量中,并将该变量传递给process,并将结果保存到另一个变量,因为它可能在这样的例子中是不安全的:

Foo f2 = null;
using (var f1 = FooFactory.createFoo()) {
// inside one can work with f1 and f2
f2 = process(f1);
}
// but outside f1's ptr is already destroyed in C dll and f2 can not use it
f2.getInfo();

我希望他们只使用这些方法中的一种,因为它们是安全的:

using var f1 = FooFactory.createFoo();
f1 = process(f1);
// or
using var f1 = process(FooFactory.createFoo());

在c++中,我可以使用std::unique_ptr来做,因为它是不可复制的。在c#中有什么方法可以做到吗?

没有完全匹配的模式。

相反,如果我在离开using块后试图使用f2,我希望Foo类型会引发ObjectDisposedException。检查状态并抛出异常可能是getInfo()(以及类似的)方法的首要职责之一。using模式在c#开发人员中根深蒂固,编写这段代码的人不会对这种行为感到惊讶。

这也是你可能想要为c#类型实现终结器的罕见情况之一。

您不能禁止,但您可以通过添加一些代码使Foo类更安全:

public unsafe class Foo : IDisposable
{
void* ptr;
internal Foo()
{
/* initialize ptr from C dll */
}
public int getInfo()
{
if (ptr is null) { // <==== test whether ptr is still valid!
return 0; // or throw an exception.
}
/* return info from ptr using dll */
}
public void Dispose()
{
/* free ptr using C dll */
ptr = null; // <==== set ptr = null when disposed!
}
}

相关内容

  • 没有找到相关文章

最新更新