2016-06-30 15 views
3

Betrachten Sie dieses Stück Code (auch in Ideone):Ist C# SortedList <TKey, TValue> .Keys.Contains-Methode, die eine Null-Ausnahme wirft, eine gute Sache?

using System; 
using System.Collections.Generic; 

class Program { 
    static void Main() { 
     Console.WriteLine(HasItem(new List<string>(), null)); 
     try { 
      Console.WriteLine(HasItem(new SortedList<string, int>().Keys, null)); 
     } catch (ArgumentNullException) { 
      Console.WriteLine("ArgumentNullException"); 
     } 
    } 

    public static bool HasItem(ICollection<string> collection, string item) { 
     return collection.Contains(item); 
    } 
} 

Problem

Der Ausgang ist

Falsch

Argument

Nach d Igling durch, wie funktioniert die SortedList<TKey, TValue> funktioniert Ich fand, dass dieser Aufruf entspricht Aufruf SortedList<TKey, TValue>.ContainsKey(TKey key) Methode, die eine ArgumentNullException dokumentiert hat.

Auf der anderen Seite, die Dokumentation für die ICollection<T>.Contains Methode heißt es:

Returns: true, wenn das Element in den ICollection<T> gefunden wird; andernfalls false.

Nun, null ist kein Teil der zweiten Sammlung in meinem Beispiel, so erwarte ich false zurückgegeben werden. Eine ArgumentNullException ist eine Verletzung der Schnittstelle und somit ein Fehler.

Was ist eine Problemumgehung für das in Produktionscode? Die Typüberprüfung ist sehr hässlich, da die .Keys -Eigenschaft eine Instanz einer privaten generischen geschachtelten Klasse zurückgibt, und ich habe keine anderen Ideen. Plus, Typprüfung ist ein wirklich böser Code-Geruch.

+3

Ich möchte Ihre Probleme haben :-) – Legends

+0

> Was ist eine Problemumgehung dafür im Produktionscode? Auch ein bisschen böse, aber fangen Sie die Ausnahme und geben Sie 'false' zurück. – Jay

+0

@Jay danke, ja, das ist eine Möglichkeit, aber es ist zu breit, leider - ich will nur die 'SortedList' Fall – Dethariel

Antwort

1

Die SortedList Klasse implementiert IDictionary, die die Key, value Natur von SortedList angibt. Aufgrund der Art und Weise, wie IDictionary Implementationen funktionieren sollen (unter Verwendung von Hashcodes, um die Schlüssel zu sortieren oder zu indizieren), können Sie kein null Objekt als Schlüssel eingeben, weil null keinen gültigen Hashcode hat. Aus diesem Grund wirft die Contains(...) Methode einen ArguementInvalidException, wenn versucht wird, null in den Parameter zu übergeben, da er weiß, dass null kein gültiger Schlüssel ist.

Wenn Sie dies für eine Produktionsumgebung "beheben" möchten (was ich nicht empfehlen würde, da dies nicht wirklich ein Problem sein sollte), würde ich empfehlen, die SortedList Klasse zu erweitern und die Contains(...) Methode zu umgehen, sicher zurückzukehren wenn die null Argument übergeben.

+0

Das ist alles wahr, aber das ist auch weit weg von der ursprünglichen Frage. Ja, die 'SortedList' ist ein Wörterbuch, okay, aber wir reden über' SortedList.Keys' hier, das ist kein Wörterbuch - es ist nur eine Sammlung. – Dethariel

+0

Plus, ich habe nur Zugriff auf die "HasItem" -Methode, die 'Main' Methode ist verbraucherdefinierten Code – Dethariel

+0

Oh, aber es scheint, dass es immer noch im selben Boot ist. Das [MSDN-Dokument] (https://msdn.microsoft.com/en-us/library/k5cf1d56 (v = vs.110) .aspx) gibt an, dass verschiedene 'Contains'-Methoden die jeweils am besten geeignete Implementierung verwenden Elternobjekt (es erwähnt explizit auch IDictionary.) Es scheint jedoch, dass die Eigenschaft "Keys" wahrscheinlich "ICollection" so implementiert hätte, dass es wie eine "Liste" funktionieren sollte, aber es könnte sich mehr wie verhalten es ist das Elternobjekt, das 'IDictionary'. Natürlich könnte es am Ende auch nur eine .NET-Eigenart sein. –

-2

Ich habe diese Zeile auf MSDN gefunden: Typ: T Das Objekt in der Sammlung zu suchen. Der Wert kann für Referenztypen null sein.

EDIT: Sie müssen diese Anweisung using für System.Linq

System.Linq verwendet wird;

Ich denke durch Verwendung von Object als mein Parameter anstelle von String, der unveränderlich ist Mein Parameter wird wirklich als Referenztyp erkannt. In jedem Fall wurde diese Funktion getestet und funktioniert. Viel Glück.

+0

Wie hast du es kompilieren lassen? Die 'ICollection ' hat keine 'Enthält (Objektwert)' Methodendeklaration – Dethariel

+0

Ich bin mir nicht sicher, was du meinst, aber ich führe meinen Code in asp.net MVC in Visual Studio 2015. Mein Framework ist 4.5. Sie laufen auf demselben Zielframework, das das einzige sein sollte, was in diesem Fall wichtig ist. Es kompiliert ohne Fehler. –

+0

Wie Sie [hier] sehen können (https://msdn.microsoft.com/en-us/library/92t2ye13 (v = vs.110) .aspx), gibt es keine solche Methode in dieser Schnittstelle. Sind Sie ** 100% sicher, dass es keine Erweiterungsmethoden gibt, die in Ihrer Umgebung bereitgestellt werden? – Dethariel