不能弄清楚为什么集合bool属性返回false

本文关键字:属性 返回 false bool 集合 弄清楚 为什么 不能 | 更新日期: 2023-09-27 18:02:38

我正在运行以下表达式,以获得基于Id的2个集合之间的增量,并确保总体结果仅包括'Active/Enabled'记录:

//Returns the right records but all IsEnabled = false
var newRecords = allRecordsFromA.Where(a => !(allRecordsFromB.Any(b => ((b.Id == a.Id) && a.IsEnabled)))).ToList();

上述结果返回A中不属于B的所有正确记录,所有记录都标记为IsEnabled = false。真正令人困惑的部分是我在应用程序的另一部分的其他2个集合上使用了完全相同的表达式,它工作。我得到了所有正确的记录,它们都被标记为.IsEnabled == true,这对我来说毫无意义。我甚至把它复制过来了,但是它不工作。

然而,如果我改变为两个步骤的过程,我得到了我想要的结果:

//Works
var newRecords = allRecordsFromA.Where(a => !(allRecordsFromB.Any(b => (b.Id == a.Id)))).ToList();
var results = newRecords.Where(x => x.IsEnabled).ToList();

我认为第一个表达式中的操作顺序是错误的,返回!应用于IsEnabled的记录,但我没有看到它。什么是不正确的在我的第一个表达式返回记录与IsEnabled == false ?

不能弄清楚为什么集合bool属性返回false

我认为你的括号不在你认为的地方。具体来说,a.IsEnabledAny语句中,然后将其取反。

allRecordsFromB.Any(b => ((b.Id == a.Id) && a.IsEnabled))

这给了你与第二个例子非常不同的逻辑。我会把a.IsEnabled移到你的Where的开始,并删除一些不必要的括号来澄清事情。

var newRecords = allRecordsFromA.Where(a => a.IsEnabled &&
                       !allRecordsFromB.Any(b => b.Id == a.Id)).ToList();

请注意,如果您有大型数据集,或者认为下面的方法会更清晰,您可以通过创建b.Id s的哈希集来加快速度(或通过某种连接,这在内部会做同样的事情)

var bIds = new HashSet<int>(allRecordsFromB.Select(b => b.Id));
var newRecords = allRecordsFromA.Where(a => a.IsEnabled &&
                                            !bIds.Contains(a.Id)).ToList();

检查a是否使能在Any内部,为negative。因此,如果条件b.Id == a.Id(对于allRecordsFromB中的某些b)和a.IsEnabled都为真,则元素将作为结果的一部分。如果两者中有一个为假,它将成为结果的一部分。

既然这与你想要的相反,你应该把IsEnabled复选框移到Any.

之外

我认为问题的一部分是你的Linq语句很难阅读,这有点违背了目的。您可以考虑这样做:

var collectionA = new List<Record>();
var collectionB = new List<Record>();
var results = collectionA.Intersect(collectionB).Where(x => x.IsEnabled);

你必须实现Equals方法:

public class Record
{
    public int Id { get; set; }
    public bool IsEnabled { get; set; }
    protected bool Equals(Record other)
    {
        return Id == other.Id;
    }
    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((Record) obj);
    }
    public override int GetHashCode()
    {
        return Id;
    }
}

或者创建一个Comparer并将其传递给Intersect方法:

public class RecordComparer : IEqualityComparer<Record>
{
    public bool Equals(Record x, Record y)
    {
        return x.Id == y.Id;
    }
    public int GetHashCode(Record obj)
    {
        return obj.GetHashCode();
    }
}