Как конвертировать результаты 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;
716   10  

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=ToHashSet

public 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

    Ничего не найдено.