为什么我不能在隐式转换中返回接口,但ExpandoObject可以吗?

时间:2012-08-31 07:51:21

标签: c# dynamic interface casting expandoobject

我有DynamicObject,我希望它可以转换为IDictionary,与ExpandoObject完全相同。例如,将ExpandoObject强制转换为IDictionary是完全有效的:

dynamic ex = new ExpandoObject ();
ex.Field = "Foobar";
IDictionary<string, object> dict = ex as IDictionary<string, object>;
Console.WriteLine (dict["Field"]);

现在我尝试将它实现到我自己的DynamicObject中:

public class MyDynamicObject : DynamicObject
{
    public Dictionary<string, object> members = new Dictionary<string, object> ();

    public override bool TryGetMember (GetMemberBinder binder, out object result)
    {
        if (members.ContainsKey (binder.Name)) {
            result = members[binder.Name];
            return true;
        }
        else {
            result = null;
            return false;
        }
    }
    public override bool TrySetMember (SetMemberBinder binder, object value)
    {
        this.members.Add (binder.Name, value);
        return true;
    }
    public static implicit operator IDictionary<string, object> (MyDynamicObject mydo) 
    {
        return (IDictionary<string, object>) mydo.members;
    }
}

但编译器将在public static implicit operator IDictionary<string, object>行失败,给出错误:“无法转换为接口类型或从接口类型转换”。如果我将隐式运算符更改为Dictionary,我可以将MyDynamicObject强制转换为Dictionary而不会出现任何问题,但不能将IDictionary强制转换为<。

ExpandoObject如何做到这一点?

3 个答案:

答案 0 :(得分:8)

ExpandoObject只是实现了IDictionary<string, object>

如果您想拥有相同的行为,还需要实施此界面并将所有来电委托给您的members字段。

这样的事情:

public class MyDynamicObject : DynamicObject, IDictionary<string, object>
{
    public Dictionary<string, object> members = new Dictionary<string, object>();

    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        return members.GetEnumerator();
    }

    public void Add(KeyValuePair<string, object> item)
    {
        members.Add(item.Key, item.Value);
    }

    // ...
}

答案 1 :(得分:0)

DLR不会审问强制转换操作符 - 因此这不起作用。

您可以继承IDictionary,也可以覆盖TryConvert方法。

由于实现IDictionary需要实现或删除大量操作,您可能会发现TryConvert路由实际上更容易实现;缺点是在TryConvert的实现中,每次调用它时几乎肯定会生成一个新的字典实例(除非你缓存结果保持最新)所以它可能会带来额外的性能影响

答案 2 :(得分:0)

它在C#规范中定义:

  

允许使用类或结构   声明来自源的转换   类型S到目标类型T提供全部   以下是真实的:

     
      
  • ...
  •   
  • S和T都不是object接口类型
  •   

请参阅this Stack Overflow回答。