Tengo una propiedad en una clase que es un ISet. Estoy tratando de obtener los resultados de una consulta linq en esa propiedad, pero no puedo entender cómo hacerlo.
Básicamente, buscando la última parte de esto:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
También podría hacer esto:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
HashedSet
. Es confuso desde entoncesC#
yLINQ
no tengo nada llamadoHashedSet
.Respuestas:
No creo que haya nada incorporado que haga esto ... pero es realmente fácil escribir un método de extensión:
Tenga en cuenta que realmente desea un método de extensión (o al menos un método genérico de alguna forma) aquí, porque es posible que no pueda expresar el tipo
T
explícitamente:No puede hacer eso con una llamada explícita al
HashSet<T>
constructor. Confiamos en la inferencia de tipos para métodos genéricos que lo hagan por nosotros.Ahora podría elegir nombrarlo
ToSet
y regresarISet<T>
, pero me quedaría conToHashSet
el tipo concreto. Esto es consistente con los operadores estándar de LINQ (ToDictionary
,ToList
) y permite una expansión futura (por ejemploToSortedSet
). También puede proporcionar una sobrecarga que especifique la comparación a utilizar.fuente
GetHashCode
yEquals
? Si no, no van a ser muy buenos en un HashSet ...ForEach
, peroToHashSet
tiene mucho más sentido: no conozco ninguna razón para no hacerToHashSet
otra cosa que la normal "no cumple con la barra de utilidad" (con la que no estoy de acuerdo, pero ...)Simplemente pase su IEnumerable al constructor de HashSet.
fuente
bar.Items
va a serT
. Dado lo fácil que es hacer este propósito general y la frecuencia con la que aparecen los tipos anónimos en LINQ, creo que vale la pena dar un paso más.Esta funcionalidad se ha agregado como método de extensión
IEnumerable<TSource>
a .NET Framework 4.7.2 :ToHashSet<TSource>(IEnumerable<TSource>)
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
fuente
Como dijo @Joel, puede pasar su enumerable. Si desea hacer un método de extensión, puede hacer:
fuente
Si solo necesita acceso de solo lectura al conjunto y la fuente es un parámetro para su método, entonces iría con
La razón es que los usuarios pueden llamar a su método con el
ISet
ya no necesita crear la copia.fuente
Hay una compilación de método de extensión en .NET Framework y en .NET core para convertir una
IEnumerable
aHashSet
: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetParece que todavía no puedo usarlo en las bibliotecas estándar de .NET (en el momento de la escritura). Entonces uso este método de extensión:
fuente
Eso es bastante simple :)
y sí T es el tipo especificado por OP :)
fuente
La respuesta de Jon es perfecta. La única advertencia es que, usando HashedSet de NHibernate, necesito convertir los resultados en una colección. ¿Hay una manera óptima de hacer esto?
o
¿O me estoy perdiendo algo más?
Editar: Esto es lo que terminé haciendo:
fuente
ToList
es generalmente más eficiente queToArray
. ¿Solo necesita implementarseICollection<T>
?En lugar de la simple conversión de IEnumerable a un HashSet, a menudo es conveniente convertir una propiedad de otro objeto en un HashSet. Podrías escribir esto como:
pero, mi preferencia sería usar selectores:
Hacen lo mismo, y el segundo es obviamente más corto, pero creo que el idioma se adapta mejor a mi cerebro (lo considero como ToDictionary).
Este es el método de extensión para usar, con soporte para comparadores personalizados como un bono.
fuente