C# 具有IList/IEnumerable的奇Linq行为

C# 具有IList/IEnumerable的奇Linq行为,c#,.net,linq,C#,.net,Linq,我有以下代码: public IList<IProductViewModel> ChildProducts { get; set; } public IList<IProductViewModel> GiftItems { get; set; } public IList<IProductViewModel> PromoItems { get; set; } public IList<IProductViewModel&

我有以下代码:

    public IList<IProductViewModel> ChildProducts { get; set; }
    public IList<IProductViewModel> GiftItems { get; set; }
    public IList<IProductViewModel> PromoItems { get; set; }

    public IList<IProductViewModel> NonGiftItems
    {
        get
        {
            return NonPromoItems.Except(GiftItems, new ProductViewModelComparer()).ToList();
        }
    }

    public IList<IProductViewModel> NonPromoItems
    {
        get
        {
            return ChildProducts.Where(p => !p.IsPromotion).ToList();
        }
    }
公共IList子产品{get;set;} 公共IList GiftItems{get;set;} 公共IList项目{get;set;} 公共物品 { 得到 { 返回非PromoItems.Exception(GiftItems,new ProductViewModelComparer()).ToList(); } } 公共非营利项目 { 得到 { return ChildProducts.Where(p=>!p.IsPromotion.ToList(); } } ProductViewModelComparer:

public class ProductViewModelComparer : IEqualityComparer<IProductViewModel>
{

    #region IEqualityComparer<IProductViewModel> Members

    public bool Equals(IProductViewModel x, IProductViewModel y)
    {
        if (Object.ReferenceEquals(x, y))
            return true;

        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        return String.Equals(x.ProductId, y.ProductId);
    }

    public int GetHashCode(IProductViewModel obj)
    {
        return obj.ProductId.GetHashCode();
    }

    #endregion
}
公共类ProductViewModelComparer:IEqualityComparer
{
#地区资格比较成员
公共布尔等于(IPProductViewModel x、IPProductViewModel y)
{
if(Object.ReferenceEquals(x,y))
返回true;
if(Object.ReferenceEquals(x,null)| | Object.ReferenceEquals(y,null))
返回false;
返回字符串.Equals(x.ProductId,y.ProductId);
}
public int GetHashCode(IPProductViewModel obj)
{
返回obj.ProductId.GetHashCode();
}
#端区
}
因此,基本上,
非促销品
(儿童产品-促销品)
,而
非促销品
(非促销品-礼品)

但是,当:

ChildProducts
=
IEnumerable[6]
promotItems
=
IEnumerable[1]
其中项目与
子产品中的1个项目匹配
GiftItems
=
IEnumerable[0]

我的结果是

非PromoItems
=
IEnumerable[5]
这是正确的
NonGiftItems
=
IEnumerable[4]
这是不正确的

不知何故,
Except(…)
在给定要减去的空列表时正在删除一个项


任何人有什么想法吗?

删除的项目是列表中另一个项目的副本吗?如果是,这是Except方法调用的标准行为:

Except有点棘手,因为它不是像您所期望的那样返回差异,而是返回差异。数学集不包含重复项(例如哈希集)

这里有一个例子来说明我的意思:

int[] ints = { 3, 3, 3 };
var result = ints.Except(5); // result contains one element only: { 3 } 
你可以阅读更多关于我在其中描述的问题

要在保留重复项的同时获得类似“Except”的功能,可以编写以下行:

var ints = new [] { 3, 42, 3 };
var excluded = new [] { 42 };
var results = ints.Where(i => !excluded.Contains(i)); // returns { 3, 3 }

删除的项目是否与列表中的其他项目重复?如果是,这是Except方法调用的标准行为:

Except有点棘手,因为它不是像您所期望的那样返回差异,而是返回差异。数学集不包含重复项(例如哈希集)

这里有一个例子来说明我的意思:

int[] ints = { 3, 3, 3 };
var result = ints.Except(5); // result contains one element only: { 3 } 
你可以阅读更多关于我在其中描述的问题

要在保留重复项的同时获得类似“Except”的功能,可以编写以下行:

var ints = new [] { 3, 42, 3 };
var excluded = new [] { 42 };
var results = ints.Where(i => !excluded.Contains(i)); // returns { 3, 3 }

我们能看到比较器代码吗?这是代码,应该不重要,因为它正在将
非PromoItems
GiftItems
进行比较,
GiftItems
为空……我们能看到比较器代码吗?这是代码,这不重要,因为它将
非promoItems
GiftItems
进行比较,
GiftItems
为空…是的,它是一个dupe,知道是否有方法执行相同的linq操作但不删除不同的条目?是的,它是一个dupe,知道是否有方法执行相同的linq操作但不删除不同的条目?