3

I wanted to make my Class Sortable(By Age) when it stored in List.

I read this : IComparable Vs IComparer and I maked my class Sortable .

public class Student : IComparable<Student>
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(Student other)
    {
        if (this.Age > other.Age)
        {
            return 1;
        }
        else if (this.Age < other.Age)
        {
            return -1;
        }
        else
        {
            return 0;
        }
    }
}

List students = new List();

// And Filling students

students.Sort();

Now , I want to make my class Distinctable , I mean when I call .Distinct() it remove duplicate students By ID .

I read IEquatable VS IEqualityComparer And same as Sort ( That give no argumants ) I expect to call .Distinct() with no passing argumants.

public class Student : IEquatable<Student>
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public bool Equals(Student other)
        {
            if (this.ID == other.ID)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
}

List students = new List();

// And Filling students

students.Distinct();

But when I use this nothing happened . WHY ?

And How can I implement IEquatable and use Distinct() with no passing argumants ?

Community
  • 1
  • 1
Parsa
  • 7,995
  • 2
  • 27
  • 37

3 Answers3

5

See what Enumerable.Distinct's docs says:

The default equality comparer, Default, is used to compare values of the types that implement the IEquatable generic interface. To compare a custom data type, you need to implement this interface and provide your own GetHashCode and Equals methods for the type.

I don't see that your Student class:

  • ...overrides Object.GetHashCode(...).
  • ...overrides Object.Equals(...)

In the other hand, Enumerable.Distinct returns:

...an unordered sequence that contains no duplicate values. It uses the default equality comparer, Default, to compare values.

Thus, you need to set the result to a variable:

var x = enumerable.Distinct();

Consider using a HashSet<T>

Perhaps you want your collection to contain unique elements. If this is the case, don't store elements in a regular collection to later call Enumerable.Distinct(), but use a HashSet<T> directly.

Once you've fixed your Student class overriding the whole methods mentioned above, you'll be able to store students as follows:

HashSet<Student> studentSet = new HashSet<Student();
studentSet.Add(new Student { ID = 1, Name = "Matías", Age = 32 });

// HashSet<T>.Add returns true if it could add the whole element. 
// In our case, this if statement will never enter!
if(studentSet.Add(new Student { ID = 1, Name = "Matías", Age = 32 }))
{
}
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • 1
    Could you please explain : why should we use " var x = students.Distinct(); " ??? It dose not work when I use " students.Distinct(); " ... – Parsa Feb 19 '17 at 20:13
  • @Parsa Well not always you need a `HashSet` but at certain point in your application flow you need to get unique elements within a collection so you call `Distinct()`. But if you've identified that you need to **store** unique elements, `HashSet` is the winner! – Matías Fidemraizer Feb 19 '17 at 20:31
  • @Parsa About `Distinct()`, did you assign the result of calling `Distinct()` to some variable? – Matías Fidemraizer Feb 19 '17 at 20:32
  • 1
    No I did not assign in variable , but as you said , I should do . I was thinking why I shoud ?! , AND I am thinking which one should I choose ? HashSet VS Distinct :))) – Parsa Feb 19 '17 at 20:36
  • @Parsa Others and me have already said that `Distinct()` doesn't modify the list but it returns a new enumerable containing the whole unique elements. – Matías Fidemraizer Feb 19 '17 at 20:39
  • @Parsa The decision about using `HashSet` or not is based on checking if you need to store unique elements or you need to be able to repeat items in the same collection. – Matías Fidemraizer Feb 19 '17 at 20:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136095/discussion-between-parsa-and-matias-fidemraizer). – Parsa Feb 19 '17 at 20:42
3

Distinct like all other LINQ methods return vale rather than modifying original collection.

Fix - asign result to variable or ToList and assign back to students.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
0

You should Implement IEquable interface and override Equals and GetHashCode methods.

  • This answer really doesn't add anything to the discussion--it merely restates the first part of Matías Fidemraizer's answer that he gave the day before, albeit in a shorter and easier form. This may be better suited as a comment to Matías' answer rather than creating a new one. – David Feb 20 '17 at 18:27