Eu tenho uma propriedade em uma classe que é um ISet. Estou tentando obter os resultados de uma consulta linq nessa propriedade, mas não consigo descobrir como fazer isso.
Basicamente, procurando a última parte disso:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
Também poderia fazer isso:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
HashedSet
parte. É confuso desde entãoC#
eLINQ
não tem nada chamadoHashedSet
.Respostas:
Eu não acho que exista algo embutido que faça isso ... mas é realmente fácil escrever um método de extensão:
Observe que você realmente deseja um método de extensão (ou pelo menos um método genérico de alguma forma) aqui, porque talvez não seja possível expressar
T
explicitamente o tipo de :Você não pode fazer isso com uma chamada explícita ao
HashSet<T>
construtor. Estamos confiando na inferência de tipo para métodos genéricos para fazer isso por nós.Agora você pode escolher nomeá-lo
ToSet
e retornarISet<T>
- mas eu continuaria comToHashSet
o tipo de concreto. Isso é consistente com os operadores LINQ padrão (ToDictionary
,ToList
) e permite expansão futura (por exemploToSortedSet
). Você também pode fornecer uma sobrecarga especificando a comparação a ser usada.fonte
GetHashCode
eEquals
? Se não, eles não vai ser muito bom em um HashSet ...ForEach
, masToHashSet
faz muito mais sentido - eu não tenho nenhuma razão para não fazerToHashSet
outra coisa senão o normal "não atende à barra de utilidade" (com a qual eu discordo, mas ...)Basta passar seu IEnumerable para o construtor do HashSet.
fonte
bar.Items
seráT
. Dado o quão fácil é tornar esse objetivo geral e a frequência com que tipos anônimos surgem no LINQ, acho que vale a pena dar um passo extra.Essa funcionalidade foi adicionada como um método de extensão
IEnumerable<TSource>
ao .NET Framework 4.7.2 :ToHashSet<TSource>(IEnumerable<TSource>)
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
fonte
Como o @Joel afirmou, você pode simplesmente passar o seu enumerável. Se você deseja fazer um método de extensão, pode:
fonte
Se você precisa apenas acessar somente leitura ao conjunto e a fonte é um parâmetro para o seu método, então eu usaria
O motivo é que os usuários podem chamar seu método com o
ISet
já, para que você não precise criar a cópia.fonte
Há um método de extensão criado na estrutura .NET e no núcleo .NET para converter um
IEnumerable
emHashSet
: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetParece que ainda não posso usá-lo nas bibliotecas padrão do .NET (no momento da redação). Então, eu uso este método de extensão:
fonte
Isso é bem simples :)
e sim T é o tipo especificado por OP :)
fonte
A resposta de Jon é perfeita. A única ressalva é que, usando o HashedSet do NHibernate, preciso converter os resultados em uma coleção. Existe uma maneira ideal de fazer isso?
ou
Ou estou faltando outra coisa?
Edit: Isto é o que acabei fazendo:
fonte
ToList
geralmente é mais eficiente queToArray
. Precisa apenas implementarICollection<T>
?Em vez da simples conversão de IEnumerable em um HashSet, geralmente é conveniente converter uma propriedade de outro objeto em um HashSet. Você pode escrever isso como:
mas, minha preferência seria usar seletores:
Eles fazem a mesma coisa, e o segundo é obviamente mais curto, mas acho que o idioma se encaixa melhor no meu cérebro (acho que é como o ToDictionary).
Aqui está o método de extensão a ser usado, com suporte para comparadores personalizados como um bônus.
fonte