2013-08-13 6 views
3
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<object> list = new List<object>(); 
      List<Dictionary<string, object>> dict = new List<Dictionary<string, object>>(); 

      Dictionary<string, object> master = new Dictionary<string, object>(); 
      master.Add("list", list); 
      master.Add("dict", dict); 

      List<object> mydict = (List<object>)master["dict"]; // this is where i get exception 
      Console.Write("Count: ", mydict.Count); 
     } 
    } 
} 

Это исключение для выделенной жирной линией. Почему такое поведение и как мне получить доступ к этому элементу? Благодаря Самантисключение из словаря из списка

+0

Вы можете только бросить его в 'List > '. 'Список <Словарь >' не может быть отправлен в 'List ' в большинстве случаев. Прочтите http://msdn.microsoft.com/en-us/library/dd799517.aspx, чтобы узнать больше о конвариантности и контравариантности. –

ответ

5

Поскольку нет List<object> под Dict ключа

var mydict = (List<Dictionary<string, object>>)master["dict"]; 
+0

Не 'Словарь <строка, объект>' объект '? –

+0

@AshBurlaczenko: Это, но «Список» из них не является «списком » из-за ограничений безопасности типа. – Jon

+0

yep, но вы не можете преобразовать тип Список <Словарь <строка, объект >> в список это называется ковариацией и контравариантностью, и в Интернете есть много ресурсов об этом. У Эрика Липперта действительно хорошая серия сообщений в блогах об этом –

3

Значение master["dict"] является List<Dictionary<string, object>>, в то время как код бросает его в List<object>. Это не работает, потому что List<T>is invariant по типу T. Для того, чтобы использовать более простой пример, это не действует:

var list = new List<string>(); 
var listOfObjects = (List<object>)list; 

Если вы каким-то образом узнать тип элемента вы вытягивать из master, то вы можете привести его обратно в соответствующий тип:

var masterDict = (List<Dictionary<string, object>>)master["dict"]; 

в качестве альтернативы, вы можете привести значение к IEnumerable<object>, потому что интерфейс ковариантен на его параметре типа:

// This is not really meaningful because you can cast to non-generic IEnumerable 
// just as well, but it works as a demonstration of what is possible. 
var mycollection = (IEnumerable<object>)master["dict"]; 
1

вы пытаетесь получить List<Dictionary<string, object>>, как a List<object> и, возможно, мышление Dictionary<string, object> является object не так ли?

да, это верно, но List<Dictionary<string, object>> делает не наследует List<object> и для этого преобразования используется недействителен!

как люди до меня сказали: сделать

(List<Dictionary<string, object>>)master["dict"]; 
0

Если вам нужно IEnumerable или ICollection методов, которые вы можете отлитые к не общему интерфейсу, как:

 ICollection mydict = (ICollection)master["dict"]; 
     Console.Write("Count: ", mydict.Count); 
Смежные вопросы