I’ve been following a post regarding extension methods from this post:
public static IEnumerable<T> Distinct<T,TKey>(this IEnumerable<T> list, Func<T,TKey> lookup) where TKey : struct {
return list.Distinct(new StructEqualityComparer<T, TKey>(lookup));
}
class StructEqualityComparer<T,TKey> : IEqualityComparer<T> where TKey : struct {
Func<T, TKey> lookup;
public StructEqualityComparer(Func<T, TKey> lookup) {
this.lookup = lookup;
}
public bool Equals(T x, T y) {
return lookup(x).Equals(lookup(y));
}
public int GetHashCode(T obj) {
return lookup(obj).GetHashCode();
}
}
Could someone explain the purpose of the where TKey : struct appended to the extension method and comparator class. Removing these statements seems to make no difference to a simple test code – both evaluations TKey are of type int on a class and struct respectively:
public struct TestMeStruct
{
public int a;
public int b;
}
public class TestMeClass
{
public int a { get; set; }
public int b { get; set; }
}
public void Test()
{
List<TestMeStruct> lstruct = new List<TestMeStruct>();
lstruct.Add(new TestMeStruct() { a = 1, b = 2 });
lstruct.Add(new TestMeStruct() { a = 3, b = 7 });
lstruct.Add(new TestMeStruct() { a = 3, b = 14 });
lstruct.Add(new TestMeStruct() { a = 32, b = 11 });
List<TestMeClass> lclass = new List<TestMeClass>();
lclass.Add(new TestMeClass() { a = 1, b = 2 });
lclass.Add(new TestMeClass() { a = 3, b = 7 });
lclass.Add(new TestMeClass() { a = 3, b = 14 });
lclass.Add(new TestMeClass() { a = 32, b = 11 });
var one = lstruct.Distinct(mem => mem.a).ToList();
var two = lclass.Distinct(mem => mem.a).ToList();
}
Both return identical lists. Much obliged for any clarity on what’s going on!
I believe you know what is generic type constraints and especially
where : struct, in short -by specifying such constraint you indicate that only value types could be used as generic type parameter, for instanceint,double, etc.In current implementation of
DistinctandStructEqualityComparerthis really does not make any difference, but idea ofStructEqualityCompareris to compare structs, its name saying this, so all classes/method which are passing through own generic type parameters required forStructEqualityComparerobligated redefine the same generic type constraints as well. In your caseDistinct()method passign its owntTparameter so obligated to redefine all constraints.