2009-12-16 9 views
13

Fondamentalmente, io voglio qualcosa di simile:C# - Hai bisogno di un'implementazione IDictionary che permetterà un null chiave

Dictionary<object, string> dict = new Dictionary<object, string>(); 
dict.Add(null, "Nothing"); 
dict.Add(1, "One"); 

ci sono eventuali incorporato nella libreria di classi base che permette questo? Il codice precedente genererà un'eccezione in fase di runtime quando si aggiunge la chiave nulla.

Grazie

+0

Solo curioso in cui avete bisogno di questo? Grazie –

risposta

11

Si potrebbe evitare di usare nulla e creare una speciale classe di valori Singleton che fa la stessa cosa. Per esempio:

public sealed class Nothing 
{ 
    public static readonly Nothing Value = new Nothing(); 
    private Nothing() {} 
} 

Dictionary<object, string> dict = new Dictionary<object, string>(); 
dict.add(Nothing.Value, "Nothing"); 
dict.add(1, "One"); 

Questo approccio non funzionare affatto se avete intenzione di fare la vostra collezione più fortemente tipizzato - diciamo ad esempio, si desidera che la chiave per essere una stringa. Poiché la stringa è sigillata, non è possibile ereditarla per creare un sostituto "valore speciale" per null. Le tue alternative diventano un po 'più complicate. È possibile:

  1. Creare un valore costante speciale per rappresentare il caso "vuoto"/"nulla". Tipo di hacky e sicuramente un percorso di confusione. Questo può essere un approccio praticabile se il dizionario è completamente privato per alcune classi di implementazione ed è possibile scrivere alcuni metodi di utilità di codifica/decodifica per evitare di diffondere la conoscenza di come si traducono le chiavi dappertutto.
  2. Creare la propria implementazione di IDictionary che delega internamente a un dizionario <> istanza - tranne che per il caso di null. Ciò viola le aspettative documentate per l'interfaccia IDictionary < che dice che le chiavi Null dovrebbero generare un'eccezione. Ma potresti riuscire a farla franca se è l'unico modo per risolvere il tuo vero problema. Funziona solo se possiedi e crea l'istanza del dizionario.
  3. Trova un modo per risolvere il tuo problema senza memorizzare una chiave "nulla" nel dizionario. Ad esempio, si consideri di non popolare la chiave nulla nel dizionario e di avere una logica caso-caso per affrontarla. Le chiavi devono essere lavabili e paragonabili a lavorare con l'implementazione sottostante, ed è per questo motivo che Null è proibito normalmente.

Come parte, la chiave del tuo dizionario ha davvero bisogno che la chiave sia object? Ciò può portare a bug sottili a causa dell'uguaglianza di riferimento utilizzata laddove è possibile che sia previsto che Equals() sia valutato come base per il confronto.

+0

L'applicazione per questo è Component One controllo utente C1FlexGrid.ImageMap che è fondamentalmente per mappare i valori memorizzati in una griglia di un'immagine. Fondamentalmente, non ho il controllo sui dati, alcuni sono nulli. – Clyde

+0

Quindi, sfortunatamente, non posso usare un oggetto fittizio come Nothing Suggestion. – Clyde

+0

Tuttavia, grazie per l'avviso == vs Equals .... mi hai appena salvato un po 'di tempo per rintracciare un altro problema .. – Clyde

2

NameValueCollection può assumere una chiave null ma non implementa IDictionary. Sarebbe tuttavia abbastanza facile derivare da DictionaryBase e fornire Aggiungi/Rimuovi/indicizzatori ecc che semplicemente sostituiscono nulla con qualcosa di simile costruito in:

class MyDictionary : DictionaryBase { 
    private readonly object nullKey = new object(); 

    void Add(object key, string value) { 
     if (key == null) { key = nullKey; } 
     .. call base methods 
    } 

} 
5

ne dici di questo?

public class NullableDictionnary<T1, T2> : Dictionary<T1, T2> 
{ 
    T2 null_value; 

    public T2 this[T1 key] 
    { 
     get 
     { 
      if (key == null) 
      { return null_value; } 
      return base[key]; 
     } 
     set 
     { 
      if (key == null) 
      { null_value = value; } 
      else 
      { base[key] = value; } 
     } 
    } 
} 
+8

Stai attento a tutte le altre funzioni che hai invalidato: Conteggio, Aggiungi, Cancella, Contiene Chiave, Contiene Valore, ecc ... Voglio dire, se stai solo hackerando, ok, ma non mi piace l'idea di creare un Classe "NullableDictionary" se hai intenzione di farlo. Quando un hack è chiaramente un hack, è meno probabile che ne venga un po 'più tardi. – phillipwei

+1

Questo non viene compilato - i metodi richiesti su '' Dictionary '' non sono virtuali. Dovresti farlo come un adattatore separato che implementa '' IDictionary ''. –

0

La chiave deve letteralmente essere NULL? La chiave della collezione è un indice. Non ha molto senso per me avere NULL per un indice in una collezione.

Forse creare una nuova classe


public class ObjectEntry 
{ 
    public object objRef; 
    public string desc; 

    public ObjectEntry(object objectReference) 
    { 
     objRef = objectReference; 
     if (objRef = null) {desc = "Nothing";} 
     else {desc = objRef.Description;} //or whatever info you can get from a proper objRef value 
    } 
} 

newObj = new ObjectEntry(null); 
dict.add(newObj, newObj.desc); 
0

Non c'è bisogno di una diversa implementazione di Dicionary.

Date un'occhiata alla mia risposta qui: https://stackoverflow.com/a/22261282/212272

Potrai anche essere in grado di mantenere il dizionario fortemente tipizzato:

var dict = new Dictionary<NullObject<int?>, string>(); 
dict[1] = "one int"; 
dict[null] = "null int"; 

Assert.AreEqual("one int", dict[1]); 
Assert.AreEqual("null int", dict[null]); 
Problemi correlati