不能弄清楚为什么集合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
?
我认为你的括号不在你认为的地方。具体来说,a.IsEnabled
在Any
语句中,然后将其取反。
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();
}
}