C#4.0’dynamic’不设置ref / out参数

我正在尝试使用DynamicObject 。 我尝试做的一件事是设置ref / out参数的值,如下面的代码所示。 但是,我无法正确设置Main()ij值(即使它们在TryInvokeMember()中设置正确)。 有没有人知道如何使用ref / out参数调用DynamicObject对象,并能够检索方法中设置的值?

 class Program { static void Main(string[] args) { dynamic proxy = new Proxy(new Target()); int i = 10; int j = 20; proxy.Wrap(ref i, ref j); Console.WriteLine(i + ":" + j); // Print "10:20" while expect "20:10" } } class Proxy : DynamicObject { private readonly Target target; public Proxy(Target target) { this.target = target; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { int i = (int) args[0]; int j = (int) args[1]; target.Swap(ref i, ref j); args[0] = i; args[1] = j; result = null; return true; } } class Target { public void Swap(ref int i, ref int j) { int tmp = i; i = j; j = tmp; } } 

更新7/15: Microsoft声称修复了下一版.NET的问题http://connect.microsoft.com/VisualStudio/feedback/details/543101/net-4-0s-dynamicobject-doesn-t-set -REF出论点

2012年9月8日更新:使用VS.NET 2012与.NET 4.0和4.5进行测试,确认:它已经修复。

这看起来可能是一个错误 – 可能在DynamicObject 。 如果你像这样添加一个Wrap方法到Proxy

 public void Wrap(ref int x, ref int y) { target.Swap(ref x, ref y); } 

然后即使仍然动态调用它(即Main的代码保持不变)代码也可以工作……所以至少一般的“动态对象如何工作”层支持pass-by-reference。

我怀疑如果这确实是DLR中的一个错误,修复.NET 4可能为时已晚 – 但是无论如何都值得报告Connect ,因此可以在Service Pack中修复它。 或者,如果这是一个故意的限制/限制,它应该在MSDN中清楚地记录(据我所知,目前不是这样)。

这不是一个错误。 正如在此处所述,DynamicObject不支持TryInvokeMember中的ref和out参数。 传递给此方法的所有内容都按“值”处理。 不久,TryInvokeMember方法只是忽略了这些关键字,这就是为什么你的方法不起作用的原因。

如果您遵循Jon Skeet建议并在inheritance自DynamicObject的类中创建自己的Wrap方法,这将是一个稍微不同的场景。 工作流程如下所示:当存在对DynamicObject的方法调用时,C#运行时绑定程序首先在类本身中查找该方法。 如果可以找到一个,则调用此方法。 此时,仍然保留有关“ref”和“out”参数的信息。 如果它找不到这样的方法,它会调用TryInvokeMember方法并简单地抛出关于“ref”和“out”关键字的信息,并开始将每个关系视为“按值”。 请记住,DynamicObject必须支持与其他语言的互操作性,而其他语言可能没有所有C#function。

没错,文档中现在没有关于“ref”和“out”的信息。 我将把它添加到下一个文档更新中。

总而言之,DynamicObject不支持pass-by-reference,因此您不想直接进行操作。