简体   繁体   English

IEnumerable的新的独特扩展方法<T>

[英]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如何实现EqualsGetHashCode 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM