c# - 完整性检查 : Do these nested . 所有调用都等同于 LINQ 中相应的 .Where 和 .SelectMany 调用?

标签 c# .net performance linq cyclomatic-complexity

我有以下代码:

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 调用。但这只能在非常大的数据集上证明,实际花费的时间非常少。如果每个元素调用一个需要较长时间的查询(例如,对数据库),如果性能差异确实是由于元素被读取的次数引起的,那么这在较小的数据集上可能更重要。但是,如果差异是由于读取元素之间的开销造成的,并且两种方法读取元素的次数相同,那么我想无论数据集大小或元素读取时间如何,性能差异总是可以忽略不计。

以下结果(来自 Visual Studio Performance Profiler): enter image description here

最佳答案

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/

相关文章:

c# - 是否可以在自定义助手中使用 HtmlHelper 对象?

c# - 用另一个覆盖授权过滤器

c# - (c++/cli) C++ 使用 C# dll 获取任何枚举成员名称

c# - Visual Studio 2010 中的 dll 导出/导入问题

c# - nUnit 3 C# - TestCaseSource - TestCaseData - 测试是否抛出异常

.net - 连接到 AS400/DB2 时在 .NET 中使用 OLEDB 参数

c# - 有没有办法从 .Net 应用程序中运行 iis express?

java - JRuby/Java Swing 工具提示重叠窗口框架将显示速度减慢至 4 Hz

Linux 服务器性能分析和负载监控软件

php - Doctrine2 性能 : Insert/Update multiple rows