Search code examples
c#lambdaexcept

Except Lambda expression also filters duplicates


If I understand correctly the Except lambda's behavior, it should return all items present in col1 but NOT in col2. In the example below, it should returns the two items with a null ID. Problems: It returns only one item with a null ID...

        var col2 = new List<StaffSkill>
        {
            new StaffSkill { SkillID = "12" },
        };

        var col1 = new List<StaffSkill>
        {
            new StaffSkill { SkillID = "12" },
            new StaffSkill { SkillID = null },
            new StaffSkill { SkillID = null },
        };

        var res = col1.Except(col2);
        if (res.Any())
        {  }

Where StaffSkill is

public class StaffSkill
{
    public string SkillID { get; set; }

    protected bool Equals(StaffSkill other)
    {
        return string.Equals(SkillID, other.SkillID, StringComparison.OrdinalIgnoreCase);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((StaffSkill) obj);
    }

    public override int GetHashCode()
    {
        return (SkillID != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(SkillID) : 0);
    }
}

Is there an explanation to this behavior. It seems the Except lambda also filters items with the same ID in the col1 collection...

What did I miss?

Thank you, Sebastien


Solution

  • this seems to be how the method is supposed to work. Please see comments sections in msdn documentation, although I do agree that it should be more clearly stated in the docs

    To get duplicates as well I would go for call like that:

    var res = col1.Where(q => !col2.Contains(q))
    

    I guess it might be a bit slower in some cases, though.