动态变量不接受没有类型转换的继承属性



我有这个动态变量,我用它来序列化一个 json 字符串。

dynamic result = serializer.Deserialize<dynamic>(json);

我从中获取result["success"],它在运行时解析为Dictionary<string, object>。然后,我应用了命名空间System.Linq,以便我可以对变量调用.First()
我写了

KeyValuePair<string, object> temp = result["success"].First();

然后我得到了错误,

"System.Collections.Generic.Dictionary"不包含"First"的定义

(但它确实如此,使用 LINQ,对吧?现在我像这样更改了代码。

KeyValuePair<string, object> temp = 
    ((Dictionary<string, object>)result["success"]).First();

它运行没有任何故障。所以我认为这可能是因为动态解析的变量。然后我尝试使用像这样的Dictionary<TKey, TValue>原生属性

var foo = result["success"].Keys;

这也没有任何故障,这让我感到困惑,因此这篇文章。

我的理解是,动态解析的变量只接受本机属性,并且需要对继承的属性进行类型转换。

我的怀疑是

  1. 我的理解正确吗?
  2. 这是预期的行为吗?
  3. 如果是这样,为什么会这样?

附言:在 C# 4.0 中编码

但是,对于 LINQ,它确实如此,对吧?

不,它没有。First() IEnumerable<T>有一个扩展方法,但不能以"正常"方式对dynamic值调用扩展方法。

但是,您可以将其用作普通的静态方法:

KeyValuePair<string, object> temp = Enumerable.First(result["success"]);

请注意,这仍将是动态绑定的 - 而当您强制转换result["success"]时,在转换之后,所有内容都只是静态类型。

这是因为扩展方法是句法糖。当您在字典上调用First时,如下所示:

dictionary.First();

编译器将其转换为:

Enumerable.First(dictionary);

但在这种情况下由于类型是dynamic,编译器对First一无所知。或者换句话说,它不会检查是否存在名为 First 的扩展方法,并尝试将代码转换为普通方法调用。在运行时,它查找实例方法。由于类型没有任何名为 First 的实例方法,因此会出现异常。要解决此问题,您只需要将方法称为正常方法,而不是像 Jon Skeet 的答案中已经说明的那样扩展。

最新更新