我有这个动态变量,我用它来序列化一个 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;
这也没有任何故障,这让我感到困惑,因此这篇文章。
我的理解是,动态解析的变量只接受本机属性,并且需要对继承的属性进行类型转换。
我的怀疑是
- 我的理解正确吗?
- 这是预期的行为吗?
- 如果是这样,为什么会这样?
附言:在 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 的答案中已经说明的那样扩展。