我有以下代码:
bool b = myList
.All(x => x.MyList
.Where(y => y.MyBool)
.All(y => y.MyList
.All(z => z.MyBool)))
这在功能上等同于:
bool b = myList
.SelectMany(x => x.MyList)
.Where(x => x.MyBool)
.SelectMany(x => x.MyList)
.All(x => x.MyBool)
我认为是的,但我的同事向我提出质疑,这种变化可能在某些情况下在功能上有所不同(例如,如果任何集合为空)。
尽管答案要么是,要么不是,但对于在可读性、圈复杂度、时间复杂度和性能方面哪一个更好的任何意见,我们也将不胜感激。
更新:
因此,我使用以下代码分析了代码:
static void Main(string[] args)
{
var myList = new List<A>();
for (var j = 0; j < 1000; j++)
{
var a = new A();
for (var k = 0; k < 1000; k++)
{
var b = new B {MyBool = true};
for (var l = 0; l < 1000; l++)
{
var c = new C {MyBool = true};
b.MyList.Add(c);
}
a.MyList.Add(b);
}
myList.Add(a);
}
for (var x = 0; x < 10000; x++)
{
bool b1 = Foo(myList);
}
for (var x = 0; x < 10000; x++)
{
bool b2 = Bar(myList);
}
}
private static bool Foo(List<A> myList)
{
return myList
.All(x => x.MyList
.Where(y => y.MyBool)
.All(y => y.MyList
.All(z => z.MyBool)));
}
private static bool Bar(List<A> myList)
{
return myList
.SelectMany(x => x.MyList)
.Where(x => x.MyBool)
.SelectMany(x => x.MyList)
.All(x => x.MyBool);
}
private class A
{
public List<B> MyList => new List<B>();
}
private class B
{
public bool MyBool { get; set; }
public List<C> MyList => new List<C>();
}
private class C
{
public bool MyBool { get; set; }
}
我发现第二种方法 (Bar
) 使用 .SelectMany
和 .Where
比第一种方法快将近 80% (Foo
) 使用嵌套的 .All
调用。但这只能在非常大的数据集上证明,实际花费的时间非常少。如果每个元素调用一个需要较长时间的查询(例如,对数据库),如果性能差异确实是由于元素被读取的次数引起的,那么这在较小的数据集上可能更重要。但是,如果差异是由于读取元素之间的开销造成的,并且两种方法读取元素的次数相同,那么我想无论数据集大小或元素读取时间如何,性能差异总是可以忽略不计。
最佳答案
myList.All // is it true for all elements in myList that…
(x => x.MyList //in their MyList property
.Where(y => y.MyBool) // those elements that have MyBool returning true
.All( // have it true for all elements in that list that…
y => y.MyList //in their MyList property
.All(z => z.MyBool) // all elements have MyBool returning true
myList.SelectMany( // for all the elements in myList
x => x.MyList) // for all elements in their MyList property…
.Where(x => x.MyBool) // that have MyBool returning true
.SelectMany( // for all those elements
x => x.MyList) // for all elements in their MyList property
.All(x => x.MyBool) // is it true that all elements have MyBool returning true
所以是的,它们具有相同的含义。特别是对于任何一种情况,任何阶段的空列表都意味着 All()
方法中的 true
,无论 true
来自空虚是否传递给调用 All()
或传递给最终 All()
的空值。
可读性是一个更主观的问题,因为所提出的问题涉及几个如果-这个-那么-那个的步骤,这本质上是繁琐的,因此会导致繁琐的表达。我赞成第一种,但不是太过分或教条化。
时间复杂度是一样的。性能可能会很大。乍一看,第二个的内部结构似乎更多地链接了枚举器,这可能会使它稍微慢一些,但我不会在这上面打赌很多钱;如果我非常关心这里的性能,我肯定会介绍两者。
关于c# - 完整性检查 : Do these nested . 所有调用都等同于 LINQ 中相应的 .Where 和 .SelectMany 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40886535/