Buu*_*yen 11 c# dynamic pass-by-reference
我在试验DynamicObject
.我尝试做的一件事是设置ref
/ out
arguments 的值,如下面的代码所示.但是,我不能够拥有的价值观 i
,并j
在Main()
正确设置(即使它们被正确设定TryInvokeMember()
).有没有人知道如何DynamicObject
使用ref
/ out
arguments 调用对象并能够检索方法中设置的值?
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;
}
}
Run Code Online (Sandbox Code Playgroud)
更新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);
}
Run Code Online (Sandbox Code Playgroud)
然后即使这仍然是动态调用的(即代码Main
保持不变)代码也可以工作......所以至少一般的"动态对象如何工作"层支持pass-by-reference.
我想,如果这是真的在DLR的错误,它可能为时已晚修为.NET 4 -但它是值得的报告连接反正所以它可以固定在一个服务包.或者,如果这是一个故意的限制/限制,它应该在MSDN中清楚地记录(据我所知,目前不是这样).
这不是一个错误.正如在此处所述,DynamicObject不支持TryInvokeMember中的ref和out参数.传递给此方法的所有内容都是"按值"处理的.不久,TryInvokeMember方法只是忽略了这些关键字,这就是为什么你的方法不起作用的原因.
如果您遵循Jon Skeet建议并在继承自DynamicObject的类中创建自己的Wrap方法,则这将是一个稍微不同的场景.工作流程如下所示:当存在对DynamicObject的方法调用时,C#运行时绑定程序首先在类本身中查找该方法.如果可以找到一个,则调用此方法.此时,仍然保留有关"ref"和"out"参数的信息.如果它找不到这样的方法,它会调用TryInvokeMember方法并简单地抛出关于"ref"和"out"关键字的信息,并开始将每个方法视为"按值".请记住,DynamicObject必须支持与其他语言的互操作性,而其他语言可能没有所有C#功能.
没错,文档中现在没有关于"ref"和"out"的信息.我将把它添加到下一个文档更新中.