Linq GroupBy with each null value as a group

后端 未结 2 893
旧巷少年郎
旧巷少年郎 2021-02-20 08:26

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

相关标签:
2条回答
  • 2021-02-20 08:54

    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());
    
    0 讨论(0)
  • 2021-02-20 08:54

    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>());
    
    0 讨论(0)
提交回复
热议问题