IEnumerable.GroupBy is not grouped

I'm having trouble using the GroupBy extension in .NET (4.5, no matter VB.NET or C #. Exaples are in C #). Here's the situation:

2 example classes:

public class Office : IEquatable<Office>
{
    public String Name { get; set; }
    public int Id { get; set; }
    public String Stuff { get; set; }

    // Compare by values
    public bool Equals(object obj)
    {
        if (obj is Office)
        {
            Office cmp = (Office) obj;
            bool result = true;
            result &= cmp.Id == this.Id;
            result &= cmp.Name == this.Name;
            result &= cmp.Stuff == this.Stuff;
            return result;
        }
        else return false;
    }

    // Hashcode by values
    public int GetHashCode()
    {
        var obj = new { Id = this.Id, Name = this.Name, Stuff = this.Stuff };
        return obj.GetHashCode();
    }

    // IEquatable uses overriden Equals implementation
    bool IEquatable<Office>.Equals(Office other)
    {
        return this.Equals(other);
    }
}

public class Company
{
    public Office Office { get; set; }
    public String Name { get; set; }
}

      

Class Office overrides equality comparison functions and implements the IEquatable interface, in which case (as I understand it) the Default EqualityComparer uses my impementation of Equals.

Now I want to group the list of companies according to the offices they occupy, for example:

        List<Company> companies = new List<Company>();
        Office office1 = new Office();
        office1.Id = 1;
        office1.Name = "Office";
        office1.Stuff = "Stuff";

        Office office2 = new Office();
        office2.Id = 1;
        office2.Name = "Office";
        office2.Stuff = "Stuff";

        Company date1 = new Company();
        date1.Office = office1;
        date1.Name = "Date 1";

        Company date2 = new Company();
        date2.Office = office2;
        date2.Name = "Date 2";

        companies.Add(date1);
        companies.Add(date2);

        IEnumerable<IGrouping<Office, Company>> grouping = companies.GroupBy(x => x.Office);

        Console.WriteLine("Groups: " + grouping.Count()); // returns 2!!!
        Console.WriteLine("Equals: " + office1.Equals(office2)); // returns true
        Console.WriteLine("Hash 1: " + office1.GetHashCode()); // returns 2067935290
        Console.WriteLine("Hash 2: " + office2.GetHashCode()); // returns 2067935290

        IEqualityComparer cmp = EqualityComparer<Office>.Default;
        Console.WriteLine("Comparer: " + cmp.Equals(office1, office2)); // returns true

      

You can see that each company has a different Office object, but in my application logic, these objects are considered equal. Therefore, the call office1.Equals(office2)

returns true, the hash codes of the object are equal, and using the EqualityComparer<Office>.Default

function Equals

also returns true.

Now the conundrum is why the call to the GroupBy office returns two groups even though the offices are "equal". The documentation states that the default EqualComparer key parameter is used ( http://msdn.microsoft.com/en-us/library/vstudio/bb534501(v=vs.100).aspx ).

Thanks for the help ~

+3


source to share


2 answers


By default, the comparator calls Object.GetHashCode

and IEquatable<Office>.Equals

.

This doesn't work for you, because you are hiding the member GetHashCode()

, not overriding it.



Your methods Equals

and GetHashCode

should be changed:

public **override** bool Equals(object obj)
public **override** int GetHashCode()

      

+8


source


Jan, you can set the modifier override

in inherited methods GetHashCode

and Equals

and then count the groups to 1. This is because when the companions are offices, the Equal

default calling method and calling method are Equal

contained in the class Office

. Correct, for example:



public class Office : IEquatable<Office>
{
    public String Name { get; set; }
    public int Id { get; set; }
    public String Stuff { get; set; }

    // Compare by values
    public override  bool Equals(object obj)
    {
        if (obj is Office)
        {
            Office cmp = (Office) obj;
            bool result = true;
            result &= cmp.Id == this.Id;
            result &= cmp.Name == this.Name;
            result &= cmp.Stuff == this.Stuff;
            return result;
        }
        else return false;
    }

    // Hashcode by values
    public override int  GetHashCode()
    {
        var obj = new { Id = this.Id, Name = this.Name, Stuff = this.Stuff };
        return obj.GetHashCode();
    }

    // IEquatable uses overriden Equals implementation
    bool IEquatable<Office>.Equals(Office other)
    {
        return this.Equals(other);
    }
}

      

+2


source







All Articles