2009-05-26 5 views
4

Je suis en train d'écrire une méthode d'extension pour insérer des données dans un dictionnaire de dictionnaires définis comme suit:méthode d'extension pour le dictionnaire des dictionnaires

items=Dictionary<long,Dictionary<int,SomeType>>() 

Ce que j'ai à ce jour est:

public static void LeafDictionaryAdd<TKEY1,TKEY2,TVALUE>(this IDictionary<TKEY1,IDictionary<TKEY2,TVALUE>> dict,TKEY1 key1,TKEY2 key2,TVALUE value) 
    { 
     var leafDictionary = 
      dict.ContainsKey(key1) 
       ? dict[key1] 
       : (dict[key1] = new Dictionary<TKEY2, TVALUE>()); 
     leafDictionary.Add(key2,value); 
    } 

mais le compilateur ne l'aime pas. L'instruction:

items.LeafDictionaryAdd(longKey, intKey, someTypeValue); 

me donne une erreur d'inférence de type.

Pour la déclaration:

items.LeafDictionaryAdd<long, int, SomeType>(longKey, intKey, someTypeValue); 

je reçois » ... ne contient pas de définition ... et la meilleure surcharge de méthode d'extension a quelques arguments non valides

Qu'est-ce que je fais mal. ?

+0

Cela a fonctionné pour moi quand j'ai essayé c'est: | – mquander

+0

Argh. Quelle douleur. Pas de mods du tout? – spender

+1

Oh, j'avais mes "items" déclarés comme IDictionary d'IDictionnaires - c'est probablement la différence clé. – mquander

Répondre

8

Certains usage générique inventive ;-P

class SomeType { } 
static void Main() 
{ 
    var items = new Dictionary<long, Dictionary<int, SomeType>>(); 
    items.Add(12345, 123, new SomeType()); 
} 

public static void Add<TOuterKey, TDictionary, TInnerKey, TValue>(
     this IDictionary<TOuterKey,TDictionary> data, 
     TOuterKey outerKey, TInnerKey innerKey, TValue value) 
    where TDictionary : class, IDictionary<TInnerKey, TValue>, new() 
{ 
    TDictionary innerData; 
    if(!data.TryGetValue(outerKey, out innerData)) { 
     innerData = new TDictionary(); 
     data.Add(outerKey, innerData); 
    } 
    innerData.Add(innerKey, value); 
} 
+0

+1 Pour être intelligent. :) –

+0

Lovely. Merci. – spender

+0

C'est le code le plus cool que j'ai vu ... beau travail – CSharpAtl

2

Essayez d'utiliser un type de béton:

public static void LeafDictionaryAdd<TKEY1,TKEY2,TVALUE>(this IDictionary<TKEY1, Dictionary<TKEY2,TVALUE>> dict,TKEY1 key1,TKEY2 key2,TVALUE value) 

voir le Dictionary<TKEY2,TVALUE> au lieu de IDictionary<TKEY2,TVALUE>

2

Je suppose qu'il s'agit d'un problème de covariance/contravariance. Votre signature de méthode attend un IDictionary de IDcitionaries, mais vous lui transmettez un IDictionary de Dictionary. Essayez d'utiliser un dictionnaire concret à la place dans votre signature de méthode, pour le dictionnaire interne.

+0

Ce n'est pas une supposition - vous avez 100% raison. –

1

Si vous spécifiez un IDictionary dans votre liste de paramètres pour la méthode Extension, , vos éléments ne correspondront pas.

Modifiez votre extension à

public static void LeafDictionaryAdd<TKEY1,TKEY2,TVALUE>(
    this IDictionary<TKEY1, Dictionary<TKEY2,TVALUE>> dict, 
    TKEY1 key1, 
    TKEY2 key2, 
    TVALUE value) 

OU Essayez et jeter vos articles à

((IDictionary<long, IDictionary<int, YourType>>)items).LeafDictionaryAdd(l, i, o); 
Questions connexes