2010-01-29 103 views
9

我有一个类,主要是一个大阵列和一些相关的家务包装。我有一个函数,它需要一个ref参数。当我将该类的一个实例传递给该函数时,我想要发送该数组。传递一个明确的演员作为参考参数(C#)

我认为明确的演员。假设我有一些具有byte [] ref参数的函数。

public void SomeFunction(ref byte[] someBytes); 

而且我有一些重载显式类型转换的类。

class SomeClass 
    { 
     byte[] someBytes; 
     public static explicit operator byte[](SomeClass someInstance) 
     { 
      return someInstance.someBytes; 
     } 
    } 

现在,我要打电话与类的函数作为参数

SomeClass someInstance = new SomeClass(); 
    SomeFunction(ref (byte[]) someInstance); 

编译器会抱怨“ref或out参数必须是可分配的变量”。我不确定我是否没有正确地按摩编译器,或者如果你真的无法做到这一点。

我认为属性或函数的返回值,但你不能传递那些由REF(和教育自己后,我明白为什么...)

我不想让阵列公共领域,但确实符合编译器的要求。 我我可以创造一个局部变量来引用与阵列,但是这是一个额外的代码行前,每个函数调用后...

编辑:它可能是值得注意的是,SomeFunction被写了第三方,我无权改变它。更糟的是,我认为他们的参数实际上不需要参考...

回答

9

一个强制转换不是一个可指定的变量;你正从你的显式转换运算符传递一个返回值。

你可以把它当作一个参考之前创建一个变量保持正常投值:

SomeClass someInstance = new SomeClass(); 
byte[] someBytes = (byte[])someInstance; 
SomeFunction(ref someBytes); 

注意,它现在是someBytes变量,它可能会重新分配。如果您想要重新分配someInstance的内部值,您必须采取措施在SomeFunction的呼叫之后以某种方式重新分配someInstance.someBytes

+0

所以事实证明,切实可行的解决办法要么是公共领域或短的方法,其唯一目的是为了掩盖一些局部变量的创建来传递。我做了一些更多的挖掘和仿制药可能有帮助也是。 – ajs410 2010-02-01 14:45:48

+0

对,一个简单的setter就足以更新someInstance。作为替代,您可以创建一个SomeFunction作为参数的接口,SomeInstance实现并通过该接口实现您的逻辑。 – 2010-02-01 15:31:26

1

你不能这样做,你需要首先将你的对象转换成变量的结果。

考虑下面的代码,如果你问被允许:

public void SomeFunction(ref byte[] someBytes) 
{ 
    someBytes = new byte[] { 1, 2, 3 }; 
} 

SomeClass someInstance = new SomeClass(); 
SomeFunction(ref (byte[]) someInstance); 
// uh-oh, what is "someInstance" now? 

为什么参数标有“裁判”,什么问题是,你想在这里解决?

+0

由于原始的第三方开发人员正在将C++库移植到.NET,所以参数标记为ref。我试图解决的问题是围绕ref跳舞,而不是使someBytes成为公共字段或创建局部变量。我选择了“明确演员”,因为我知道家政领域将会丢失。我希望someInstance只是将someBytes的引用传递给SomeFunction。与使用公共字段没什么不同,但强制显式转换会使其不易被滥用。 – ajs410 2010-01-29 23:31:34

+1

那么,“参考”和“出”参数需要一个支持变量,真的没有办法绕过,所以你只需要定义变量,因为你已经发现了。你当然可以在你自己的类中创建shim方法来为你做这个翻译,然后调用这些方法,然后进行转换,存储一个变量,并调用实际的方法,但那可能会不是一个好的解决方案。 – 2010-01-29 23:46:10

+0

最终的解决方案实际上涉及创建对byte []的引用的本地副本并重新创建本地副本。这在技术上违反了裁判点,但我敢肯定,第三方程序员认为C#中的ref与C++中的&相同,这是不正确的。 – ajs410 2010-02-01 14:52:39

1

可以在C#中用作ref参数的值范围受CLR允许的限制。它在CLI规范中的第12.4.1.5.2和12.1.6节中进行了说明。1,并且包括

  • 参数的对象的当前方法
  • 局部变量
  • 成员字段
  • 静电场
  • 数组元素

的铸造不适合任何的这些因此不能用作ref的值。在通过引用传递它之前,您需要将它分配给像本地一样的值。

+0

感谢您参考规格!我一段时间都没有涉足C#,所以从某种意义上说,当我全面探索该语言的各种特性时,这更像是一个学术问题......并且确实有很多。 – ajs410 2010-02-01 14:48:13

0

你是否真的必须施放ref参数?在我的情况下,这样的工作很好。

byte[] someInstance = (byte[])new SomeClass(); 
SomeFunction(ref someInstance);