Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ GroupBy using anonymous types working better than it should

Tags:

c#

linq

Suppose I have a class defined as:

public class DataHolder
{
    public string PropA { get; set; }
    public string PropB { get; set; }
    public string PropC { get; set; }
    public int PropD { get; set; }
}

and have an instance of an array of DataHolders declared as:

    var x=new DataHolder[]{
        new DataHolder(){PropA="A",PropB="X",PropC="J",PropD=1},
        new DataHolder(){PropA="A",PropB="Y",PropC="J",PropD=3},
        new DataHolder(){PropA="A",PropB="Y",PropC="J",PropD=5},
        new DataHolder(){PropA="B",PropB="X",PropC="K",PropD=7},
        new DataHolder(){PropA="B",PropB="Y",PropC="L",PropD=9},
        new DataHolder(){PropA="C",PropB="X",PropC="J",PropD=11},
        new DataHolder(){PropA="C",PropB="X",PropC="J",PropD=13},
        new DataHolder(){PropA="C",PropB="Y",PropC="J",PropD=15},
        new DataHolder(){PropA="C",PropB="Z",PropC="J",PropD=17}
    };

and I run a LINQ GroupBy query against it like so:

    var t = x.GroupBy(c => new { A = c.PropA, B = c.PropB, C = c.PropC })

When I examine the results, I find that t has 7 elements, which is the number of distinct PropA,PropB,PropC combinations in the array, which is the effect that I want (yay!). But then I thought, it shouldn't actually work, because each new instance of the anonymous type should be unequal to the others, and t should have 9 elements. Why is it working as I first thought it should?

like image 895
Boluc Papuccuoglu Avatar asked Dec 06 '25 03:12

Boluc Papuccuoglu


2 Answers

Because for anonymous types:

Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashcode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

(taken from MSDN)

So they DO have an overloaded Equals that makes a "sane" property-by-property comparison.

like image 97
xanatos Avatar answered Dec 08 '25 17:12

xanatos


Note that two anonymous types are "equal" if both of the following are true:

1) they are the same type

(MSDN: "If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.")

2) all their properties are equal.

Note that the "same order" is important here:

var a = new {A = 1, B = "Dog"};
var b = new {A = 1, B = "Dog"};
var c = new {B = "Dog", A = 1};

a.Equals(b) // true
a.Equals(c) // false -- a and c are instances of different types.
like image 24
Eren Ersönmez Avatar answered Dec 08 '25 16:12

Eren Ersönmez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!