I have an object with a nullable int property \"GroupId\".
With a List of this object, I would like to do a GroupBy on this \"GroupId\". But if I do it, all the null val
This is probably the shortest solution:
var grouped = MyList.GroupBy(f => f.GroupId != null ? (object)f.GroupId : new object(), key => new { Object = key });
Note that the "key" of the groups will be of object
type. For null
elements I create a new "empty" object
. The equality comparer of objects will make so that they are all different. For not-null numbers I simply box them in an object. Boxed integers maintain the equality operator. So:
new object().Equals(new object()) == false // always
and
((object)1).Equals((object)1) == true // always
and
((object)1).Equals((object)2) == false // always
a more correct solution would be implementing an IEqualityComparer<int?>
public class MyComparer : IEqualityComparer<int?> {
public bool Equals(int? x, int? y) {
if (x == null || y == null) {
return false;
}
return x.Value == y.Value;
}
public int GetHashCode(int? obj) {
return obj.GetHashCode(); // Works even if obj is null :-)
}
}
and using it:
var grouped2 = MyList.GroupBy(f => f.GroupId, key => new { Object = key }, new MyComparer());
Generic Comparer that can be used without boxing.
public class NullableComparer<T> : IEqualityComparer<T?>
where T : struct
{
public bool Equals(T? x, T? y)
{
if (x == null || y == null)
{
return false;
}
return x.Equals(y);
}
public int GetHashCode(T? obj)
{
return obj.GetHashCode();
}
}
You would then use it like:
// where GroupId as a nullable Guid
var grouped = MyList.GroupBy(f => f.GroupId, new NullableComparer<Guid>());