在这种情况下我有错误,Visual Studio说unreadDialogs.key有另一个(TLAbsPeer)类型,
var unreadDialogs = dialogs.dialogs.lists
.Where(t => t.unread_count > 0 && t.peer.GetType() == typeof(TLPeerChannel))
.ToDictionary(t => t.peer, t => t.unread_count);
foreach (KeyValuePair <TLPeerChannel,int> channel in unreadDialogs)
{ }
但是当我写这篇文章时,一切都好。
var unreadDialogs = dialogs.dialogs.lists
.Where(t => t.unread_count > 0 && t.peer.GetType() == typeof(TLPeerChannel))
.Select(t => t.peer);
foreach (TLPeerChannel channel in unreadDialogs)
{ }
为什么?
P.S peer可以是TLPeerChannel或TLPeerUser
答案 0 :(得分:0)
您必须区分静态类型(即编译时类型)和运行时类型。例如,t.peer
可以静态类型为object
,但在运行时包含对TLPeerChannel
对象的引用。如果是这种情况,那么t => t.peer
将创建一个密钥类型为object
的字典,无论运行时类型如何,因为密钥的类型是在编译时确定的。
您可以将其更改为t => (TLPeerChannel)t.peer
。
var unreadDialogs = dialogs.dialogs.lists
.Where(t => t.unread_count > 0 && t.peer.GetType() == typeof(TLPeerChannel))
.ToDictionary(t => (TLPeerChannel)t.peer, t => t.unread_count);
foreach (KeyValuePair <TLPeerChannel,int> channel in unreadDialogs)
{ }
答案 1 :(得分:-1)
因为,在使用ToDictionary
构建字典时,它会将创建的字典的键键入t.peer
的类型,而不是TLPeerChannel
。我推测t.peer
的类型是基本类型,可以是TLPeerChannel
或TLPeerUser
。因此,当您尝试使用类型为KeyValuePair
的密钥TLPeerChannel
访问该字典时,这不是字典中密钥的类型。
你可以通过强制转换为你要使用的类型来解决它......
var unreadDialogs = dialogs.dialogs.lists
.Where(t => t.unread_count > 0 && t.peer.GetType() == typeof(TLPeerChannel))
.ToDictionary(t => ((TLPeerChannel) t.peer), t => t.unread_count);
foreach (KeyValuePair <TLPeerChannel,int> channel in unreadDialogs)
{ }
告诉ToDictionary
方法,字典键的类型是所有键的类型,是TLPeerChannel。
问题与协方差和逆变以及隐式转换是否可证明是安全的有关。在您的第一个代码中,编译器不能假设从TLAbsPeer转换为TLPeerChannel是可证明安全的。 Eric Lippert更好地解释了这一点并提供了一些参考文献 here 。