Distinct () с лямбдой?

Итак, у меня есть перечислимое число, и я хочу получить от него разные значения.

При использовании System.Linq, конечно же, есть метод расширения под названием Distinct. В простом случае его можно использовать без параметров, например:

var distinctValues = myStringList.Distinct();

Хорошо, но если у меня есть перечислимое количество объектов, для которых мне нужно указать равенство, единственная доступная перегрузка:

var distinctValues = myCustomerList.Distinct(someEqualityComparer);

Аргумент компаратора равенства должен быть экземпляром IEqualityComparer<T>. Я, конечно, могу это сделать, но это несколько многословно и, ну, в общем, неуклюже.

Я ожидал, что перегрузка потребует лямбда-выражения, например Func<T, T, bool>:

var distinctValues = myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);

Кто-нибудь знает, существует ли такое расширение или какой-либо эквивалентный обходной путь? Или я что-то упускаю?

В качестве альтернативы, есть ли способ указать IEqualityComparer inline (смущаю меня)?

Обновить

Я нашел ответ Андерса Хейлсберга на сообщение на форуме MSDN по этой теме. Он говорит:

Проблема, с которой вы собираетесь столкнуться, заключается в том, что когда два объекта сравниваются равными, они должны иметь одно и то же возвращаемое значение GetHashCode (иначе хеш-таблица, используемая внутри Distinct, не будет работать правильно). Мы используем IEqualityComparer, потому что он объединяет совместимые реализации Equals и GetHashCode в единый интерфейс.

Полагаю, это имеет смысл.


person Tor Haugen    schedule 19.08.2009    source источник
comment
см. stackoverflow.com/questions/1183403/ для решения с использованием GroupBy   -  person    schedule 13.09.2011
comment
Спасибо за новости Андерса Хейлсберга!   -  person Tor Haugen    schedule 28.09.2011
comment
Нет, это не имеет смысла - как два объекта, содержащие одинаковые значения, могут возвращать два разных хэш-кода ??   -  person G.Y    schedule 06.11.2015
comment
Это может помочь - решение для .Distinct(new KeyEqualityComparer<Customer,string>(c1 => c1.CustomerId)) и объяснить, почему GetHashCode () важен для правильной работы.   -  person marbel82    schedule 12.10.2016
comment
Связанный / возможный дубликат: LINQ Distinct () для определенного свойства   -  person Marc.2377    schedule 13.12.2018
comment
@ G.Y Это имеет смысл, потому что равенство не является абсолютным. Например, можно было бы рассматривать Hello и hello как равные в данном контексте, и в этом весь смысл возможности предоставить свой собственный компаратор равенства: предоставить определение равенства, адаптированное для домена / контекста, в котором вы находитесь.   -  person AnorZaken    schedule 03.03.2020
comment
Теперь вы можете использовать встроенный метод DistinctBy в .Net 6, например DistinctBy (x = ›x.CustomerId).   -  person Furkan Öztürk    schedule 17.06.2021


Ответы (19)


Мне кажется, вы хотите, чтобы DistinctBy от MoreLINQ. Затем вы можете написать:

var distinctValues = myCustomerList.DistinctBy(c => c.CustomerId);

Вот урезанная версия DistinctBy (без проверки на нуль и без возможности указать свой собственный компаратор ключей):

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
     (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}
person Jon Skeet    schedule 19.08.2009
comment
Я знал, что лучший ответ будет опубликован Джоном Скитом, просто прочитав заголовок сообщения. Если это как-то связано с LINQ, Скит - ваш человек. Прочтите «C # In Depth», чтобы получить божественные знания linq. - person Shawn J. Molloy; 16.01.2014
comment
отличный ответ !!! кроме того, для всех VB_Complainers по поводу yield + дополнительной библиотеки foreach можно переписать как return source.Where(element => knownKeys.Add(keySelector(element))); - person denis morozov; 04.03.2014
comment
Я получаю Exception stackoverflow.com/questions/13405568/ при использовании этого DistinctBy в запросе LinqToSQL. приведенный ниже код работает для меня. общедоступный статический IEnumerable ‹T› DistinctBy ‹T› (этот список IEnumerable ‹T›, Func ‹T, объект› propertySelector) {return list.GroupBy (propertySelector) .Select (x = ›x.FirstOrDefault ()); } - person sudhAnsu63; 15.04.2015
comment
@ sudhAnsu63 это ограничение LinqToSql (и других поставщиков linq). Цель LinqToX состоит в том, чтобы преобразовать ваше лямбда-выражение C # в собственный контекст X. То есть LinqToSql преобразует ваш C # в SQL и выполняет эту команду везде, где это возможно. Это означает, что любой метод, который находится в C #, не может быть передан через linqProvider, если нет способа выразить его в SQL (или любом другом поставщике linq, который вы используете). Я вижу это в методах расширения для преобразования объектов данных для просмотра моделей. Вы можете обойти это, материализуя запрос, вызывая ToList () перед DistinctBy (). - person Michael Blackburn; 17.11.2015
comment
И всякий раз, когда я возвращаюсь к этому вопросу, я все время удивляюсь, почему они не приняли хотя бы часть MoreLinq в BCL. - person Shimmy Weitzhandler; 22.05.2017
comment
@Shimmy: Я, конечно, приветствовал бы это ... Я не уверен, что это осуществимо. Но я могу поднять его в .NET Foundation ... - person Jon Skeet; 22.05.2017
comment
@JonSkeet Кстати, я удалил свой первый комментарий. - person Shimmy Weitzhandler; 22.05.2017
comment
@JonSkeet, это был действительно профессиональный ответ. Спасибо - person Selman; 17.03.2018
comment
Для всех, кто беспокоится о доходности VB.NET, он был добавлен (docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/) - person Brian J; 27.07.2018
comment
Любое решение для Linq to SQL? - person Shimmy Weitzhandler; 03.09.2019
comment
@Shimmy: ответ Карло может работать в LINQ to SQL ... Я не уверен. - person Jon Skeet; 03.09.2019

Подвести итоги. Я думаю, что большинство людей, которые пришли сюда, как я, хотят получить самое простое возможное решение, без использования каких-либо библиотек и с максимально возможной производительностью.

(Я считаю, что принятый метод группировки по методу является излишним с точки зрения производительности.)

Вот простой метод расширения с использованием интерфейса IEqualityComparer, который работает также для нулевых значений.

Использование:

var filtered = taskList.DistinctBy(t => t.TaskExternalId).ToArray();

Код метода расширения

public static class LinqExtensions
{
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
    {
        GeneralPropertyComparer<T, TKey> comparer = new GeneralPropertyComparer<T,TKey>(property);
        return items.Distinct(comparer);
    }   
}
public class GeneralPropertyComparer<T,TKey> : IEqualityComparer<T>
{
    private Func<T, TKey> expr { get; set; }
    public GeneralPropertyComparer (Func<T, TKey> expr)
    {
        this.expr = expr;
    }
    public bool Equals(T left, T right)
    {
        var leftProp = expr.Invoke(left);
        var rightProp = expr.Invoke(right);
        if (leftProp == null && rightProp == null)
            return true;
        else if (leftProp == null ^ rightProp == null)
            return false;
        else
            return leftProp.Equals(rightProp);
    }
    public int GetHashCode(T obj)
    {
        var prop = expr.Invoke(obj);
        return (prop==null)? 0:prop.GetHashCode();
    }
}
person Anestis Kivranoglou    schedule 09.12.2015

Нет, для этого нет такой перегрузки метода расширения. Раньше это меня расстраивало, и поэтому я обычно пишу вспомогательный класс для решения этой проблемы. Цель состоит в том, чтобы преобразовать Func<T,T,bool> в IEqualityComparer<T,T>.

Пример

public class EqualityFactory {
  private sealed class Impl<T> : IEqualityComparer<T,T> {
    private Func<T,T,bool> m_del;
    private IEqualityComparer<T> m_comp;
    public Impl(Func<T,T,bool> del) { 
      m_del = del;
      m_comp = EqualityComparer<T>.Default;
    }
    public bool Equals(T left, T right) {
      return m_del(left, right);
    } 
    public int GetHashCode(T value) {
      return m_comp.GetHashCode(value);
    }
  }
  public static IEqualityComparer<T,T> Create<T>(Func<T,T,bool> del) {
    return new Impl<T>(del);
  }
}

Это позволяет вам написать следующее

var distinctValues = myCustomerList
  .Distinct(EqualityFactory.Create((c1, c2) => c1.CustomerId == c2.CustomerId));
person JaredPar    schedule 19.08.2009
comment
Однако у этого есть неприятная реализация хэш-кода. Легче создать IEqualityComparer<T> из проекции: stackoverflow.com/questions/188120/ - person Jon Skeet; 19.08.2009
comment
(Просто чтобы объяснить мой комментарий о хэш-коде - с этим кодом очень легко получить Equals (x, y) == true, но GetHashCode (x)! = GetHashCode (y). Это в основном ломает что-то вроде хеш-таблицы .) - person Jon Skeet; 19.08.2009
comment
Я согласен с возражением против хэш-кода. Тем не менее, +1 за выкройку. - person Tor Haugen; 19.08.2009
comment
@Jon, да, я согласен, что исходная реализация GetHashcode не совсем оптимальна (ленился). Я переключил его на использование EqualityComparer ‹T› .Default.GetHashcode (), что немного более стандартно. По правде говоря, единственная гарантированно работающая реализация GetHashcode в этом сценарии - это просто возвращать постоянное значение. Прекращает поиск по хэш-таблице, но гарантирует его функциональную корректность. - person JaredPar; 19.08.2009
comment
@JaredPar: Совершенно верно. Хэш-код должен соответствовать используемой вами функции равенства, которая предположительно не используется по умолчанию, иначе вы бы не беспокоились :) Вот почему я предпочитаю использовать проекцию - вы можете таким образом получить как равенство, так и разумный хэш-код. Это также уменьшает дублирование вызывающего кода. По общему признанию, это работает только в тех случаях, когда вам нужна одна и та же проекция дважды, но это все случаи, которые я видел на практике :) - person Jon Skeet; 19.08.2009
comment
У меня это работает, только если я заменю <T,T> на <T>. В противном случае есть ошибки компиляции. Я что-то упускаю? - person Uwe Keim; 10.07.2014
comment
Как уже упоминалось в других комментариях, эта реализация нарушена, потому что созданный IEqualityComparer<> использует GetHashCode(T), который несовместим с Equals(T, T). Использование с .Distinct не будет работать правильно. Например, в ответе мы помещаем все экземпляры с одинаковым .CustomerId в один и тот же класс равенства. Но все они не будут иметь одинаковый хэш-код, поэтому они будут потеряны в хеш-таблице, используемой Distinct. В результате будут получены разные экземпляры с одинаковым .CustomerId. - person Jeppe Stig Nielsen; 18.12.2017
comment
Это не сработает, если вы сравните только член объекта, хэш-код его полностью пропустит. Лучше принудительно предоставить лямбду для него или вместо этого использовать лямбда и отражение для получения доступа к члену - person UberFace; 28.11.2018

Сокращенное решение

myCustomerList.GroupBy(c => c.CustomerId, (key, c) => c.FirstOrDefault());
person Arasu RRK    schedule 20.08.2014
comment
Не могли бы вы объяснить, почему это улучшено? - person Keith Pinson; 20.08.2014
comment
Это действительно хорошо сработало для меня, когда Конрада нет. - person neoscribe; 17.04.2019

Это будет делать то, что вы хотите, но я не знаю о производительности:

var distinctValues =
    from cust in myCustomerList
    group cust by cust.CustomerId
    into gcust
    select gcust.First();

По крайней мере, это не многословно.

person Gordon Freeman    schedule 06.10.2010

Вот простой метод расширения, который делает то, что мне нужно ...

public static class EnumerableExtensions
{
    public static IEnumerable<TKey> Distinct<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector)
    {
        return source.GroupBy(selector).Select(x => x.Key);
    }
}

Жаль, что они не встроили такой отдельный метод во фреймворк, но эй-хо.

person David Kirkland    schedule 01.03.2012
comment
это лучшее решение без необходимости добавлять библиотеку morelinq. - person toddmo; 19.09.2014
comment
Но мне пришлось изменить x.Key на x.First() и изменить возвращаемое значение на IEnumerable<T> - person toddmo; 19.09.2014
comment
@toddmo Спасибо за отзыв :-) Да, звучит логично ... Я обновлю ответ после дальнейшего изучения. - person David Kirkland; 19.09.2014
comment
никогда не поздно сказать спасибо за решение, простое и чистое - person Ali; 24.02.2018

То, что я использовал, хорошо сработало для меня.

/// <summary>
/// A class to wrap the IEqualityComparer interface into matching functions for simple implementation
/// </summary>
/// <typeparam name="T">The type of object to be compared</typeparam>
public class MyIEqualityComparer<T> : IEqualityComparer<T>
{
    /// <summary>
    /// Create a new comparer based on the given Equals and GetHashCode methods
    /// </summary>
    /// <param name="equals">The method to compute equals of two T instances</param>
    /// <param name="getHashCode">The method to compute a hashcode for a T instance</param>
    public MyIEqualityComparer(Func<T, T, bool> equals, Func<T, int> getHashCode)
    {
        if (equals == null)
            throw new ArgumentNullException("equals", "Equals parameter is required for all MyIEqualityComparer instances");
        EqualsMethod = equals;
        GetHashCodeMethod = getHashCode;
    }
    /// <summary>
    /// Gets the method used to compute equals
    /// </summary>
    public Func<T, T, bool> EqualsMethod { get; private set; }
    /// <summary>
    /// Gets the method used to compute a hash code
    /// </summary>
    public Func<T, int> GetHashCodeMethod { get; private set; }

    bool IEqualityComparer<T>.Equals(T x, T y)
    {
        return EqualsMethod(x, y);
    }

    int IEqualityComparer<T>.GetHashCode(T obj)
    {
        if (GetHashCodeMethod == null)
            return obj.GetHashCode();
        return GetHashCodeMethod(obj);
    }
}
person Kleinux    schedule 19.08.2009
comment
@Mukus Я не уверен, почему вы спрашиваете здесь об имени класса. Мне нужно было назвать класс как-нибудь, чтобы реализовать IEqualityComparer, поэтому я просто поставил префикс My. - person Kleinux; 11.06.2015

Все решения, которые я видел здесь, основаны на выборе уже сопоставимого поля. Однако если нужно сравнить по-другому, это решение здесь, похоже, обычно работает для чего-то вроде:

somedoubles.Distinct(new LambdaComparer<double>((x, y) => Math.Abs(x - y) < double.Epsilon)).Count()
person Dmitry Ledentsov    schedule 14.11.2012
comment
Что такое LambdaComparer, откуда вы это импортируете? - person Patrick Graham; 25.01.2018
comment
@PatrickGraham ссылается в ответе: brendan.enrick .com / post / - person Dmitry Ledentsov; 29.01.2018

Возьмите другой способ:

var distinctValues = myCustomerList.
Select(x => x._myCaustomerProperty).Distinct();

Последовательность возвращает отдельные элементы, сравнивая их по свойству _myCaustomerProperty.

person Bob    schedule 12.06.2017
comment
Пришел сюда, чтобы сказать это. ЭТО должен быть принятым ответом - person Still.Tony; 18.12.2018
comment
Нет, это не должен быть принятый ответ, если все, что вам нужно, - это отдельные значения настраиваемого свойства. Общий вопрос OP заключался в том, как вернуть отдельные объекты на основе определенного свойства объекта. - person tomo; 27.05.2019

Вы можете использовать LambdaEqualityComparer:

var distinctValues
    = myCustomerList.Distinct(new LambdaEqualityComparer<OurType>((c1, c2) => c1.CustomerId == c2.CustomerId));


public class LambdaEqualityComparer<T> : IEqualityComparer<T>
    {
        public LambdaEqualityComparer(Func<T, T, bool> equalsFunction)
        {
            _equalsFunction = equalsFunction;
        }

        public bool Equals(T x, T y)
        {
            return _equalsFunction(x, y);
        }

        public int GetHashCode(T obj)
        {
            return obj.GetHashCode();
        }

        private readonly Func<T, T, bool> _equalsFunction;
    }
person Валентин Миронов    schedule 26.10.2018

Вы можете использовать InlineComparer

public class InlineComparer<T> : IEqualityComparer<T>
{
    //private readonly Func<T, T, bool> equalsMethod;
    //private readonly Func<T, int> getHashCodeMethod;
    public Func<T, T, bool> EqualsMethod { get; private set; }
    public Func<T, int> GetHashCodeMethod { get; private set; }

    public InlineComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
    {
        if (equals == null) throw new ArgumentNullException("equals", "Equals parameter is required for all InlineComparer instances");
        EqualsMethod = equals;
        GetHashCodeMethod = hashCode;
    }

    public bool Equals(T x, T y)
    {
        return EqualsMethod(x, y);
    }

    public int GetHashCode(T obj)
    {
        if (GetHashCodeMethod == null) return obj.GetHashCode();
        return GetHashCodeMethod(obj);
    }
}

Пример использования:

  var comparer = new InlineComparer<DetalleLog>((i1, i2) => i1.PeticionEV == i2.PeticionEV && i1.Etiqueta == i2.Etiqueta, i => i.PeticionEV.GetHashCode() + i.Etiqueta.GetHashCode());
  var peticionesEV = listaLogs.Distinct(comparer).ToList();
  Assert.IsNotNull(peticionesEV);
  Assert.AreNotEqual(0, peticionesEV.Count);

Источник: https://stackoverflow.com/a/5969691/206730
Использование IEqualityComparer для Union
Могу ли я указать свой явный компаратор типов в строке?

person Kiquenet    schedule 13.10.2014

Сложный способ сделать это - использовать расширение Aggregate(), используя словарь в качестве аккумулятора со значениями ключ-свойство в качестве ключей:

var customers = new List<Customer>();

var distincts = customers.Aggregate(new Dictionary<int, Customer>(), 
                                    (d, e) => { d[e.CustomerId] = e; return d; },
                                    d => d.Values);

И решение в стиле GroupBy использует ToLookup():

var distincts = customers.ToLookup(c => c.CustomerId).Select(g => g.First());
person Arturo Menchaca    schedule 07.04.2016
comment
Хорошо, но почему бы вместо этого просто не создать Dictionary<int, Customer>? - person ruffin; 30.01.2018

Я предполагаю, что у вас есть IEnumerable, и в вашем примере делегата вы хотите, чтобы c1 и c2 ссылались на два элемента в этом списке?

Я считаю, что вы могли бы добиться этого с помощью самостоятельного присоединения var DifferentResults = from c1 в myList, присоединиться к c2 в myList на

person MattH    schedule 19.08.2009

Если Distinct() не дает уникальных результатов, попробуйте следующее:

var filteredWC = tblWorkCenter.GroupBy(cc => cc.WCID_I).Select(grp => grp.First()).Select(cc => new Model.WorkCenter { WCID = cc.WCID_I }).OrderBy(cc => cc.WCID); 

ObservableCollection<Model.WorkCenter> WorkCenter = new ObservableCollection<Model.WorkCenter>(filteredWC);
person Andy Singh    schedule 07.12.2011

В пакете Microsoft System.Interactive есть версия Distinct, которая принимает лямбда-выражение ключевого селектора. По сути, это то же самое, что и решение Джона Скита, но людям может быть полезно узнать об этом и проверить остальную часть библиотеки.

person Niall Connaughton    schedule 16.06.2015

Вот как это сделать:

public static class Extensions
{
    public static IEnumerable<T> MyDistinct<T, V>(this IEnumerable<T> query,
                                                    Func<T, V> f, 
                                                    Func<IGrouping<V,T>,T> h=null)
    {
        if (h==null) h=(x => x.First());
        return query.GroupBy(f).Select(h);
    }
}

Этот метод позволяет вам использовать его, указав один параметр, например .MyDistinct(d => d.Name), но он также позволяет вам указать условие наличия в качестве второго параметра, например:

var myQuery = (from x in _myObject select x).MyDistinct(d => d.Name,
        x => x.FirstOrDefault(y=>y.Name.Contains("1") || y.Name.Contains("2"))
        );

N.B. Это также позволит вам указать другие функции, например, .LastOrDefault(...).


Если вы хотите раскрыть только условие, вы можете сделать его еще проще, реализовав его как:

public static IEnumerable<T> MyDistinct2<T, V>(this IEnumerable<T> query,
                                                Func<T, V> f,
                                                Func<T,bool> h=null
                                                )
{
    if (h == null) h = (y => true);
    return query.GroupBy(f).Select(x=>x.FirstOrDefault(h));
}

В этом случае запрос будет выглядеть так:

var myQuery2 = (from x in _myObject select x).MyDistinct2(d => d.Name,
                    y => y.Name.Contains("1") || y.Name.Contains("2")
                    );

N.B. Здесь выражение проще, но обратите внимание, что .MyDistinct2 использует .FirstOrDefault(...) неявно.


Примечание. В приведенных выше примерах используется следующий демонстрационный класс

class MyObject
{
    public string Name;
    public string Code;
}

private MyObject[] _myObject = {
    new MyObject() { Name = "Test1", Code = "T"},
    new MyObject() { Name = "Test2", Code = "Q"},
    new MyObject() { Name = "Test2", Code = "T"},
    new MyObject() { Name = "Test5", Code = "Q"}
};
person Matt    schedule 26.07.2016

IEnumerable лямбда-расширение:

public static class ListExtensions
{        
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, int> hashCode)
    {
        Dictionary<int, T> hashCodeDic = new Dictionary<int, T>();

        list.ToList().ForEach(t => 
            {   
                var key = hashCode(t);
                if (!hashCodeDic.ContainsKey(key))
                    hashCodeDic.Add(key, t);
            });

        return hashCodeDic.Select(kvp => kvp.Value);
    }
}

Использование:

class Employee
{
    public string Name { get; set; }
    public int EmployeeID { get; set; }
}

//Add 5 employees to List
List<Employee> lst = new List<Employee>();

Employee e = new Employee { Name = "Shantanu", EmployeeID = 123456 };
lst.Add(e);
lst.Add(e);

Employee e1 = new Employee { Name = "Adam Warren", EmployeeID = 823456 };
lst.Add(e1);
//Add a space in the Name
Employee e2 = new Employee { Name = "Adam  Warren", EmployeeID = 823456 };
lst.Add(e2);
//Name is different case
Employee e3 = new Employee { Name = "adam warren", EmployeeID = 823456 };
lst.Add(e3);            

//Distinct (without IEqalityComparer<T>) - Returns 4 employees
var lstDistinct1 = lst.Distinct();

//Lambda Extension - Return 2 employees
var lstDistinct = lst.Distinct(employee => employee.EmployeeID.GetHashCode() ^ employee.Name.ToUpper().Replace(" ", "").GetHashCode()); 
person Shantanu    schedule 19.07.2015

Я нашел это как самое простое решение.

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
        (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        return source.GroupBy(keySelector).Select(x => x.FirstOrDefault());
    }
person Tulshi Das    schedule 01.06.2021

person    schedule
comment
Превосходно! Это действительно легко инкапсулировать в метод расширения, например DistinctBy (или даже Distinct, поскольку подпись будет уникальной). - person Tomas Aschan; 27.07.2011
comment
У меня не работает! ‹Метод« Первый »можно использовать только как завершающую операцию запроса. Вместо этого рассмотрите возможность использования метода «FirstOrDefault» в этом случае. ›Даже я попробовал« FirstOrDefault », это не сработало. - person JatSing; 25.09.2011
comment
@TorHaugen: Просто имейте в виду, что создание всех этих групп требует затрат. Это не может передавать поток ввода и в конечном итоге буферизует все данные, прежде чем что-либо вернуть. Конечно, это может не иметь отношения к вашей ситуации, но я предпочитаю элегантность DistinctBy :) - person Jon Skeet; 28.09.2011
comment
@JonSkeet: этого достаточно для программистов VB.NET, которые не хотят импортировать дополнительные библиотеки только для одной функции. Без ASync CTP VB.NET не поддерживает оператор yield, поэтому потоковая передача технически невозможна. Спасибо за ответ. Я буду использовать его при кодировании на C #. ;-) - person Alex Essilfie; 11.12.2011
comment
@AlexEssilfie: Технически это возможно, но не так просто, как с языковой поддержкой. Нет ничего, что могло бы помешать вам реализовать IEnumerable<T> себя в VB ... - person Jon Skeet; 11.12.2011
comment
@JatSing: вы должны использовать Linq to Entities. - person Josh Mouch; 14.02.2012
comment
Будет ли производительность лучше при использовании метода GroupBy с двумя параметрами, как предлагается здесь: stackoverflow.com/a/1183877/8479? - person Rory; 08.08.2012
comment
Ошибка, если CustomerId является ссылочным типом, не имеющим реализации для сравнения равенства значений, например cust.CustomerId=new[] { '1', '2', '3' }. - person Ken Kin; 04.08.2013
comment
Вдохновленный вашим сообщением, почему бы не выбрать сначала, а затем использовать разные? Думаю, это меньше накладных расходов. myCustomerList.Select (cust = ›cust.CustomerId) .Distinct (); - person Ben Gripka; 06.09.2014
comment
@BenGripka: Это не совсем то же самое. Он дает вам только идентификаторы клиентов. Я хочу целого покупателя :) - person ryanman; 16.10.2014
comment
Я выбираю этот подход по сравнению с подходом HashSet, потому что я работаю со списками, в которых обычно меньше 5 элементов и почти всегда меньше примерно 10, поэтому я ожидаю, что накладные расходы на хеширование будут выше, чем циклы и сравнение. . - person David; 24.04.2017
comment
Я предпочитаю использовать таким образом .KEY, (g = ›g.ProcessName) .Select (s =› s.Key) .ToList (); - person Lucas Rodrigues Sena; 02.05.2017
comment
Это решение не отвечает на вопрос, но предлагает альтернативу или, по крайней мере, не аргументирует неадекватность вопроса. Люди не понимают разницы между ответом на мой вопрос и, пожалуйста, предложите альтернативу. - person impulsgraw; 14.12.2020