Ich habe eine Eigenschaft für eine Klasse, die ein ISet ist. Ich versuche, die Ergebnisse einer Linq-Abfrage in diese Eigenschaft zu übertragen, kann aber nicht herausfinden, wie das geht.
Grundsätzlich auf der Suche nach dem letzten Teil davon:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
Könnte auch das tun:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
HashedSet
weglassen. Es ist nur verwirrend daC#
undLINQ
hat nichts genanntHashedSet
.Antworten:
Ich glaube nicht , dass irgendetwas eingebaut ist, das dies tut ... aber es ist wirklich einfach, eine Erweiterungsmethode zu schreiben:
Beachten Sie, dass Sie hier wirklich eine Erweiterungsmethode (oder zumindest eine generische Methode in irgendeiner Form) möchten, da Sie den Typ von möglicherweise nicht
T
explizit ausdrücken können:Sie können dies nicht mit einem expliziten Aufruf des
HashSet<T>
Konstruktors tun . Wir verlassen uns auf Typinferenz für generische Methoden, um dies für uns zu tun.Jetzt könnten Sie es benennen
ToSet
und zurückkehrenISet<T>
- aber ich würde beiToHashSet
und dem konkreten Typ bleiben . Dies steht im Einklang mit den Standard-LINQ-Operatoren (ToDictionary
,ToList
) und ermöglicht eine zukünftige Erweiterung (zToSortedSet
. B. ). Möglicherweise möchten Sie auch eine Überladung bereitstellen, die den zu verwendenden Vergleich angibt.quelle
GetHashCode
undEquals
? Wenn nicht, werden sie in einem HashSet nicht viel gut sein ...ForEach
, aber esToHashSet
macht viel mehr Sinn - ich kenne keinen Grund, etwasToHashSet
anderes als das normale "Erfüllt nicht die Nützlichkeitsleiste" zu tun (dem ich nicht zustimmen würde, aber ...)Übergeben Sie einfach Ihre IEnumerable an den Konstruktor für HashSet.
quelle
bar.Items
wirdT
. Angesichts der Tatsache, wie einfach es ist, diesen allgemeinen Zweck zu erfüllen, und wie häufig anonyme Typen in LINQ vorkommen, lohnt es sich meiner Meinung nach, den zusätzlichen Schritt zu tun.Diese Funktionalität wurde als Erweiterungsmethode
IEnumerable<TSource>
für .NET Framework 4.7.2 hinzugefügt :ToHashSet<TSource>(IEnumerable<TSource>)
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
quelle
Wie bei @Joel angegeben, können Sie Ihre Aufzählung einfach übergeben. Wenn Sie eine Erweiterungsmethode ausführen möchten, können Sie Folgendes tun:
quelle
Wenn Sie nur schreibgeschützten Zugriff auf das Set benötigen und die Quelle ein Parameter für Ihre Methode ist, würde ich mit gehen
Der Grund ist, dass die Benutzer Ihre Methode möglicherweise mit dem
ISet
bereits aufrufen, sodass Sie die Kopie nicht erstellen müssen.quelle
Im .NET Framework und im .NET Core wird eine Erweiterungsmethode zum Konvertieren
IEnumerable
von a in Folgendes erstelltHashSet
: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetEs scheint, dass ich es noch nicht in .NET-Standardbibliotheken verwenden kann (zum Zeitpunkt des Schreibens). Also benutze ich diese Erweiterungsmethode:
quelle
Das ist ziemlich einfach :)
und ja T ist der von OP angegebene Typ :)
quelle
Jons Antwort ist perfekt. Die einzige Einschränkung ist, dass ich mit HiberSet von NHibernate die Ergebnisse in eine Sammlung konvertieren muss. Gibt es einen optimalen Weg, dies zu tun?
oder
Oder fehlt mir noch etwas?
Edit: Das habe ich letztendlich gemacht:
quelle
ToList
ist in der Regel effizienter alsToArray
. Muss es nur implementiert werdenICollection<T>
?Anstelle der einfachen Konvertierung von IEnumerable in ein HashSet ist es häufig zweckmäßig, eine Eigenschaft eines anderen Objekts in ein HashSet zu konvertieren. Sie könnten dies schreiben als:
Ich würde jedoch lieber Selektoren verwenden:
Sie machen das Gleiche und die zweite ist offensichtlich kürzer, aber ich finde, dass die Redewendung besser zu meinem Gehirn passt (ich denke, es ist wie ToDictionary).
Hier ist die zu verwendende Erweiterungsmethode mit Unterstützung für benutzerdefinierte Vergleicher als Bonus.
quelle