It took me a few re-reads to see what you meant. But, I think you mean to group by each of the list object's properties, while ignoring null values in the property compare.
So here's a solution by using a custom equality comparer (called ItemComparer
in the code sample below) that meets your special requirement. You can then plug this comparer into the linq GroupBy function and voila:
void Main()
{
var items = GetItems();
foreach (var grp in items.GroupBy(i => i, new ItemComparer()))
{
foreach (var g in grp)
{
Console.WriteLine($"Grouping {grp.Key.Code}: {g.Amount?.ToString() ?? "null"} + {g.Type ?? "null"} + {g.Code?? "null"}");
}
Console.WriteLine("--------------------------------------------------");
}
}
public class ItemComparer : IEqualityComparer<Item>
{
// Here we consider a null on either side of the compare to be true as per your
// requirements. Normally a null compare returns: false.
public bool Equals(Item a, Item b)
{
return
(a.Amount == null || b.Amount == null || a.Amount == b.Amount) &&
(a.Type == null || b.Type == null || a.Type == b.Type) &&
(a.Code == null || b.Code == null || a.Code == b.Code);
}
// The linq operators will try a hash code comparison first, if they are the same,
// then it will use the Equals function. So always returning 0 will force it to use
// the Equals method.
public int GetHashCode(Item item)
{
return 0;
}
}
public List<Item> GetItems()
{
return new List<Item>
{
new Item { Amount = 50, Type = "Test", Code = "AA" },
new Item { Amount = 50, Type = "Test2", Code = "BB" },
new Item { Amount = null, Type = "Test", Code = "AA" },
new Item { Amount = 45, Type = "Test3", Code = "CC" },
new Item { Amount = 50, Type = "Test", Code = null },
new Item { Amount = 50, Type = "Test", Code = "AB" }
};
}
public class Item
{
public int? Amount { get; set; }
public string Type { get; set; }
public string Code { get; set; }
}
This returns the following:
Grouping AA: 50 + Test + AA
Grouping AA: null + Test + AA
Grouping AA: 50 + Test + null
--------------------------------------------------
Grouping BB: 50 + Test2 + BB
--------------------------------------------------
Grouping CC: 45 + Test3 + CC
--------------------------------------------------
Grouping AB: 50 + Test + AB
--------------------------------------------------