[英]New Distinct Extension Method for IEnumerable<T>
I've been trying to add a new extension method for to distinct an IEnumerable<T>
object. 我一直在尝试添加新的扩展方法以区分
IEnumerable<T>
对象。 For both learning and applying purposes. 用于学习和应用目的。
The logic behind should do something like this : (this works) 背后的逻辑应该做这样的事情:
// sis is a DbContext by the way
List<MyObj> objs = sis.MyObjs.ToList();
// objs contains duplicate entities
List<MyObj> _objs = new List<MyObj>();
foreach(MyObj e in MyObjs)
{
if (_ems.Contains(e) == false) _ems.Add(e);
}
foreach(MyObj e in _ems)
{
Console.WriteLine(e.ID); // Distinction happens
}
I've wrote a new extension method to do the same as above lines. 我写了一个新的扩展方法来做与上面几行相同的操作。
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> en)
{
foreach(T f in en)
{
if (en.Contains(f) == false) yield return f;
}
}
but it didn't work. 但这没用。 And the strange thing is, I've also tried these (separately)
奇怪的是,我也曾尝试过这些
objs.Distinct(); // default Distinct() method in Linq
objs.GroupBy(t => t.ID).Select(t => t.FirstOrDefault());
but they also couldn't have distinct the objects. 但他们也无法区分对象。 The only thing works, first logic that i wrote above.
唯一起作用的是我上面编写的第一个逻辑。
So, how could one possibly write a new extension to do the same thing as first logic does ? 那么,一个人怎么可能写一个新的扩展来做和第一个逻辑一样的事情呢?
This all depends on how T
implements Equals
and GetHashCode
. 这一切都取决于
T
如何实现Equals
和GetHashCode
。 If the implementation is the default inherited from object
then this will be reference equality. 如果实现是从
object
继承的默认值,则这将是引用相等。
Unless T
has a level of immutability like string
, then all instances will be different, they'll have different references. 除非
T
具有像string
这样的不变性,否则所有实例将不同,它们将具有不同的引用。
You can add an overload to your Distinct
method to accept an IEqualityComparer<T>
implementation to override T
s behaviour. 您可以将重载添加到
Distinct
方法中,以接受IEqualityComparer<T>
实现以覆盖T
的行为。
Additionaly , your current implementation is more of a existence stripper, see a proposed alternative below. 另外 ,您当前的实现更多是存在剥离器,请参阅下面的建议替代方案。
public static IEnumerable<T> Distinct<T>(
this IEnumerable<T> source,
IEqualityComparer<T> comparer = null)
{
if (comparer == null)
{
comparer = EqualityComparer<T>.Default;
}
var seen = new HashSet<T>(comparer);
foreach (var t in source)
{
if (seen.Contains(t))
{
continue;
}
yield return t;
seen.Add(t);
}
}
When using List and Dictionaries always remember to override Equals and GetHashCode in the T entity that you wish to use. 使用列表和字典时,请始终记住要覆盖您想要使用的T实体中的Equals和GetHashCode。
In your example above you are comparing references (addresses) and not the intended values of those addresses. 在上面的示例中,您正在比较引用(地址)而不是这些地址的预期值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.