C#4.0'vynamic'不设置ref / out参数

时间:2010-03-19 06:10:52

标签: c# dynamic pass-by-reference

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

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-out-arguments

的问题

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

3 个答案:

答案 0 :(得分:5)

这似乎可能是一个错误 - 可能在DynamicObject。如果您将Wrap方法添加到Proxy,请执行以下操作:

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

然后即使这仍然是动态调用的(即Main中的代码保持不变)代码也可以工作...所以至少一般的“动态对象如何工作”层支持传递参考

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:2)

总而言之,DynamicObject不支持pass-by-reference,因此您不想直接做到这一点。