Как конвертировать результаты linq в HashSet или HashedSet
у меня есть свойство в классе, который является ISet. Я пытаюсь получить результаты запроса LINQ в собственность, но не могу понять, как это сделать.
в основном, глядя на последнюю часть этого:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
может также сделать это:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
10 ответов:
Я не думаю есть что-нибудь встроенное, что делает это... но это действительно легко написать метод расширения:
public static class Extensions { public static HashSet<T> ToHashSet<T>( this IEnumerable<T> source, IEqualityComparer<T> comparer = null) { return new HashSet<T>(source, comparer); } }обратите внимание, что вы действительно хотите метод расширения (или, по крайней мере, общий метод какой-либо формы) здесь, потому что вы не можете быть в состоянии выразить тип
Tконкретно:var query = from i in Enumerable.Range(0, 10) select new { i, j = i + 1 }; var resultSet = query.ToHashSet();вы не можете сделать это с явным вызовом
HashSet<T>конструктор. Мы полагаемся на вывод типа для универсальных методов, чтобы сделать это для нас.теперь может выбрать имя
ToSetи возвратISet<T>- но я бы придерживалсяToHashSetи конкретный тип. Это согласуется со стандартными операторами LINQ (ToDictionary,ToList) и позволяет для будущего расширения (напримерToSortedSet). Вы также можете предоставить перегрузку, определяющую сравнение для использования.
просто передайте свой IEnumerable в конструктор для HashSet.
HashSet<T> foo = new HashSet<T>(from x in bar.Items select x);
Как заявил @Joel,вы можете просто передать свой перечисляемый. Если вы хотите сделать метод расширения, вы можете сделать:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items) { return new HashSet<T>(items); }
эта функция была добавлена в качестве метода расширения на
IEnumerable<TSource>to .NET Framework 4.7.2:
Если вам нужен только доступ только для чтения к набору, а источник является параметром вашего метода, то я бы пошел с
public static ISet<T> EnsureSet<T>(this IEnumerable<T> source) { ISet<T> result = source as ISet<T>; if (result != null) return result; return new HashSet<T>(source); }причина в том, что пользователи могут вызвать ваш метод с помощью
ISetуже так вам не нужно создавать копию.
Это очень просто :)
var foo = new HashSet<T>(from x in bar.Items select x);и да T-это тип, указанный OP:)
существует метод расширения build в .NET framework и в .NET core для преобразования
IEnumerableдоHashSet: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetpublic static System.Collections.Generic.HashSet<TSource> ToHashSet<TSource> (this System.Collections.Generic.IEnumerable<TSource> source);похоже, что я пока не могу использовать его в стандартных библиотеках .NET (на момент написания статьи). Поэтому я использую этот метод расширения:
[Obsolete("In the .NET framework and in NET core this method is available, " + "however can't use it in .NET standard yet. When it's added, please remove this method")] public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null) => new HashSet<T>(source, comparer);
ответ Джона совершенен. Единственное предостережение заключается в том, что, используя HashedSet NHibernate, мне нужно преобразовать результаты в коллекцию. Есть ли оптимальный способ сделать это?
ISet<string> bla = new HashedSet<string>((from b in strings select b).ToArray());или
ISet<string> bla = new HashedSet<string>((from b in strings select b).ToList());или я упускаю что-то еще?
Edit: это то, что я закончил делать:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) { return new HashSet<T>(source); } public static HashedSet<T> ToHashedSet<T>(this IEnumerable<T> source) { return new HashedSet<T>(source.ToHashSet()); }
вы можете просто использовать конструктор IEnumerable HashSet.
HashSet<T> foo = new HashSet<T>((from x in bar.Items select x).ToArray());
, а не простое преобразование интерфейсов IEnumerable для поиска HashSet, это часто оказывается удобным преобразовать собственность другого объекта в поиска HashSet. Вы могли бы написать это так:
var set = myObject.Select(o => o.Name).ToHashSet();но, мое предпочтение было бы использовать селекторы:
var set = myObject.ToHashSet(o => o.Name);Они делают то же самое, и второй, очевидно, короче, но я считаю, что идиома лучше подходит для моего мозга (я думаю, что это похоже на ToDictionary).
вот метод расширения для использования, с поддержкой пользовательские компараторы в качестве бонуса.
public static HashSet<TKey> ToHashSet<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer = null) { return new HashSet<TKey>(source.Select(selector), comparer); }
Comments