Reputation: 368
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!
Upvotes: 2
Views: 623
Reputation: 62045
I am pretty sure you are not asking what 'where' means. You are asking 'what is the point in putting it there'.
In the original post that you linked to, Sam Saffron said "A similar helper class can be built to compare objects. (It will need to do better null handling)". So, with your little test suite nothing goes wrong, because you are not passing any nulls. Try passing nulls, and it will blow up.
What probably happened is that Sam Saffron wrote an EqualityComparer, and then realized that he should be checking for nulls all over the place, which would make his code kind of unsuitable as an example, so instead of adding null checks he just renamed it to StructEqualityComparer and he made it only work with structs.
Upvotes: 1
Reputation: 62544
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 instance int
, double
, etc.
In current implementation of Distinct
and StructEqualityComparer
this really does not make any difference, but idea of StructEqualityComparer
is to compare structs, its name saying this, so all classes/method which are passing through own generic type parameters required for StructEqualityComparer
obligated redefine the same generic type constraints as well. In your case Distinct()
method passign its ownt T
parameter so obligated to redefine all constraints.
Upvotes: 1
Reputation: 46193
The where
keyword is used to qualify a generic parameter. In this case, you are indicating that the StructEqualityComparer
must take something that is a value type (or struct
), so that an equality comparison will compare by value rather than by reference.
Upvotes: 1
Reputation: 15242
From msdn
The where clause is used to specify constraints on the types that can be used as arguments for a type parameter defined in a generic declaration. For example, you can declare a generic class, MyGenericClass, such that the type parameter T implements the IComparable interface:
public class MyGenericClass where T:IComparable { }
Upvotes: 3