РЕДАКТИРОВАНИЕ : Это - теперь часть MoreLINQ.
то, В чем Вы нуждаетесь, "отлично -" эффективно. Я не полагаю, что это - часть LINQ как есть, хотя довольно легко записать:
public static IEnumerable DistinctBy
(this IEnumerable source, Func keySelector)
{
HashSet seenKeys = new HashSet();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
Так для нахождения отличных значений, использующих просто Id
свойство, Вы могли использовать:
var query = people.DistinctBy(p => p.Id);
И использовать несколько свойств, можно использовать анонимные типы, которые реализуют равенство соответственно:
var query = people.DistinctBy(p => new { p.Id, p.Name });
Непротестированный, но это должно работать (и это теперь, по крайней мере, компилирует).
Это принимает компаратор по умолчанию для ключей, хотя - если Вы хотите передать в компараторе равенства, просто передайте его на HashSet
конструктор.
Основное отличие состоит в том, что в в вашем первом примере, без прототипа, реализация функций getSecret
и setSecret
будет находиться на каждом экземпляре spy1.
Во втором примере функции определены в прототипе, и все экземпляры ссылаются на них напрямую, вы можете проверить это:
var bond = new spy1("007"),
bond2 = new spy1("007");
bond.getSecret === bond2.getSecret; // <-- false since they are two functions
var smart = new spy2("86"),
smart2 = new spy2("86");
smart.getSecret === smart2.getSecret; // <-- true since is the same function
// on all instances
Также обратите внимание на то, что прокомментировал @TJ, в вашем втором примере, используя прототип, у вас нет доступа к закрытию функции конструктора,и для этого вы создаете глобальную переменную window.secret
.
Если вы собираетесь работать с привилегированными методами , расширение прототипа не является вариантом, все методы, которые требуют доступ к переменным, определенным в области видимости функции конструктора, должен быть объявлен внутри нее ...
См. также: Замыкания .
В вашем первом примере вы создаете новые функции для каждого экземпляра объекта всякий раз, когда вы создаете новый экземпляр. Во втором случае создается только одна копия функции, которая используется всеми экземплярами.
Второй способ может сэкономить память. Вы также можете использовать цепочку прототипов для реализации наследования.
Кстати, ваш второй пример не будет работать так, как написано. переменная secret
в spy2
является локальной для конструктора. В функциях setSecret
и getSecret
в прототипе вы обращаетесь к одной глобальной переменной.
Со второй версией вы получаете более чистый «конструктор».