我有一个KeyValuePairs列表。我通常会使用ToDictionary
。
但是我只是注意到错误消息(如下所示)有关于显式转换的内容,这意味着我实际上可以将列表转换为Dictionary<...>
。我怎么能这样做?
Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<System.Collections.Generic.KeyValuePair<int,string>>' to 'System.Collections.Generic.Dictionary<int, string>'. An explicit conversion exists (are you missing a cast?)
示例代码:
Dictionary<int, string> d = new Dictionary<int, string>() {
{3, "C"},
{2, "B"},
{1, "A"},
};
var s = d.OrderBy(i => i.Value);
d = s;
答案 0 :(得分:69)
意味着我实际上可以将列表转换为字典
嗯,这意味着强制转换在编译时是有效的。这并不意味着它会在执行时工作。
可能此代码可以正常工作:
IOrderedEnumerable<KeyValuePair<string, string>> pairs = GetPairs();
Dictionary<string, string> dictionary = (Dictionary<string, string>) pairs;
...但仅当GetPairs()
返回的值是从[{1}}派生的类时,该类也实现了Dictionary<,>
。在普通代码中,实际的情况不太可能。编译器不能阻止你尝试,但它不会很好地结束。 (特别是,如果你使用问题中的代码并使用标准的LINQ to Objects执行它,它肯定会在执行时失败。)
你应该坚持使用IOrderedEnumerable<KeyValuePair<string, string>>
......虽然你也应该意识到你将失去顺序,所以没有必要先订购它。
使用您问题中的代码显示此内容:
ToDictionary
编译,但在执行时失败,如预测的那样:
未处理的异常:System.InvalidCastException:无法将类型为
Dictionary<int, string> d = new Dictionary<int, string>() { {3, "C"}, {2, "B"}, {1, "A"}, }; var s = d.OrderBy(i => i.Value); d = (Dictionary<int, string>) s;
的对象强制转换为'System.Linq.OrderedEnumerable`2[System.Collections.Generic.KeyValuePair`2[System.Int32,System.String],System.String]'
类型。
在Test.Main()
作为一个背景知识,你可以始终从任何接口类型转换为非密封类(“目标”),即使该类型没有实现接口,因为它是可能的另一个派生自“target”的类来实现接口。
来自C#5规范的第6.2.4节:
显式引用转换为:
- ...
- 从任何类型
'System.Collections.Generic.Dictionary`2[System.Int32,System.String]'
到任何接口类型S
,提供的T
未被密封并提供{ {1}}未实施S
。- ...
(S
实施T
的情况由隐式参考转化涵盖。)
如果您尝试隐式转换值并且没有可用的隐式转换,但是有可用的显式转换,编译器会在您的问题中给出警告。这意味着您可以使用强制转换来修复编译器错误,但是您需要知道它在执行时失败的可能性。
以下是一个例子:
S
错误讯息:
T
所以我们可以添加一个演员:
using System;
class Test
{
static void Main()
{
IFormattable x = GetObject();
}
static object GetObject()
{
return DateTime.Now.Second >= 30 ? new object() : 100;
}
}
此时,代码将工作大约一半的时间 - 另一半,它会抛出异常。