首页 > 编程语言 >C#-听说有人不推荐使用Linq!?

C#-听说有人不推荐使用Linq!?

时间:2024-07-04 13:57:28浏览次数:13  
标签:C# sum Linq int 听说 void foreach public row

先说结论

linq和直接遍历的性能差异点主要还是迭代方式数组字符串这类的foreach都是专门有优化的,而linq都是通用的泛型调用迭代器,如果刚好遇到这类数据又需要高性能就尽量不用linq,其他类型或性能要求不高的还是linq香。(ps:linq写的不好不能怪linq)

背景

起初是看到有人写的博客说***不推荐使用Linq!( https://mp.weixin.qq.com/s/FuF1Wp2eMxbamY5-uMErVQ ),还被多个wx订阅号转载,本能地觉得离谱呀!
what?!
unbelievable!

自测

仔细查看,发现这代码写的有问题呀,然后自己重写了一版

部分代码

    [Benchmark]
    public void SumWithLinq()
    {
        int sum = _row.Sum(c => c == ',' ? 0 : c-'0');
    }

    [Benchmark(Baseline = true)]
    public void SumWithLoop()
    {
        int sum = 0;
        for (int i = 0; i < _row.Length; i++)
        {
            var c= _row[i];
            if (c!= ',')
                sum += c-'0';

        }
    }

测试结果

分析

虽然比那个博主的数据好了很多,但是linq确实比直接使用循环慢得多。查看Sum的内部实现,意料之中是用的迭代器,于是继续添加测试

再测

添加foreach测试代码

    [Benchmark]
    public void SumWithForeach()
    {
        int sum = 0;
        foreach (var c in _row)
        {
            if (c != ',')
                checked
                {
                    sum += int.CreateChecked(c-'0');
                }
        }
    }

测试结果

分析

foreach和for居然没有什么区别,那差距是在哪里呢?突然意识到sum的调用方是IEnumerable,于是又添加了如下测试

再测

添加测试代码

    [Benchmark]
    public void SumWithEnumerable()
    {
        int sum = 0;
        foreach (var c in _row as IEnumerable<char>)
        {
            if (c != ',')
                checked
                {
                    sum += int.CreateChecked(c-'0');
                }
        }
    }

测试结果

分析

直接对string做foreach和将string转为可迭代对象再foreach居然差这么多,string的foreach底层实现可能有优化

查看ILSpy

直接foreach:

调用迭代器:

深入了解foreach

参阅文档:.NET 本质论 - 了解 C# foreach 的内部工作原理和使用 yield 的自定义迭代器
https://learn.microsoft.com/zh-cn/archive/msdn-magazine/2017/april/essential-net-understanding-csharp-foreach-internals-and-custom-iterators-with-yield

附完整代码

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

internal class Program
{
    static void Main(string[] args)
    {
        BenchmarkRunner.Run<LinqTest>();
    }
}

[MemoryDiagnoser, MemoryRandomization]
public class LinqTest
{
    private static readonly string _row = "1,2,3,4,5,6,7,8,9,10";

    [Benchmark]
    public void SumWithLinq()
    {
        int sum = _row.Sum(c => c == ',' ? 0 : c-'0');
    }


    [Benchmark]
    public void SumWithEnumerable()
    {
        int sum = 0;
        foreach (var c in _row as IEnumerable<char>)
        {
            if (c != ',')
                checked
                {
                    sum += int.CreateChecked(c-'0');
                }
        }
    }

    [Benchmark]
    public void SumWithForeach()
    {
        int sum = 0;
        foreach (var c in _row)
        {
            if (c != ',')
                checked
                {
                    sum += int.CreateChecked(c-'0');
                }
        }
    }

    [Benchmark(Baseline = true)]
    public void SumWithLoop()
    {
        int sum = 0;
        for (int i = 0; i < _row.Length; i++)
        {
            var c= _row[i];
            if (c!= ',')
                sum += c-'0';

        }
    }
}

标签:C#,sum,Linq,int,听说,void,foreach,public,row
From: https://www.cnblogs.com/LaughAtSelfsWrong/p/18283479

相关文章

  • 服务器Oracle数据库损坏修复
    当Oracle数据库在服务器上损坏时,修复过程需要谨慎且系统地进行,以确保数据的完整性和系统的稳定性。一、初步诊断与评估检查错误日志:首先,检查Oracle数据库的错误日志(如alertlog和tracefiles),这些日志通常包含有关数据库损坏的详细信息,如错误代码、失败的操作等。确定损坏范围:......
  • H3C华三服务器raid报错数据恢复
    一、确认RAID状态与硬盘状态检查RAID状态:通过服务器的管理界面或命令行工具检查RAID的状态,确认是RAID配置错误、信息丢失还是硬盘故障导致的RAID报错。检查硬盘状态:检查服务器的所有硬盘的状态,包括健康状况、读写性能等,以确定是否有硬盘出现物理故障或逻辑错误。二、尝试恢......
  • 什么是C/S,什么是B/S
    C/S全称:Client/Server即:客户端/服务端解释:通过应用程序使用服务,即我们使用的软件,比如微信,QQ之类的软件B/S全程:Browser/Server即:浏览器/服务端  解释:通过浏览器使用服务,即我们打开浏览器访问的网站,比如博客园,CSDN,GitHub等网站 举例①操作系统和硬件系......
  • 【往届会议论文已完成EI、SCOPUS检索】第四届电力系统与能源互联网国际学术会议(PoSEI
    第三届电力系统与能源互联网国际学术会议(PoSEI2023)由福州大学主办,将于2024年7月26日-28日在中国福州召开。能源互联网是将系统性思维和数字化技术与能源生产、传输、存储、消费以及能源市场深度融合的新型生态化能源系统,以可再生能源优先,以电力为基础,通过多能协同、供需......
  • MySQL中的可插拔身份验证(Pluggable Authentication)(二)
    PluggableAuthentication(PAM,即可插拔式认证模块)是一种高效且灵活的用户级别的认证方式,广泛应用于现代操作系统,特别是Linux服务器中。它允许数据库管理员(DBAs)为MySQL用户帐户选择和更改不同的认证方法。1身份验证插件客户端/服务器兼容性可插拔身份验证使MySQL帐户在选择身......
  • MySQL中的可插拔身份验证(Pluggable Authentication)(一)
    PluggableAuthentication(PAM,即可插拔式认证模块)是一种高效且灵活的用户级别的认证方式,广泛应用于现代操作系统,特别是Linux服务器中。它允许数据库管理员(DBAs)为MySQL用户帐户选择和更改不同的认证方法。当客户端尝试连接到MySQL服务器时,服务器会使用客户端提供的用户名和主机......
  • Apache Hadoop完全分布式集群搭建指南
    Hadoop发行版本较多,Cloudera版本(Cloudera’sDistributionIncludingApacheHadoop,简称CDH)收费版本通常用于生产环境,这里用开源免费的ApacheHadoop原始版本。下载:ApacheHadoop版本下载:Indexof/hadoop/commonHadoop基础知识可查看本专栏其它篇章:ApacheHadoop的核心组成......
  • JUC(java.util.concurrent)的常见类
    JUC(java.util.concurrent)的常见类Callable(这是一个interface接口)这个也是创建线程的一种方式Runnable能表示一个任务(run方法)返回:voidCallable也能表示一个任务(call方法)返回:一个具体的值,类型可以通过泛型参数来指定(Object)如果进行多线程操作,只是关心多线......
  • Java 中的字符串替换方法详解:replace, replaceAll 和 replaceFirst
    在Java中,字符串的替换是一种常见的操作,特别是在处理文本和格式化输出时。Java提供了几种不同的方法来实现字符串替换,其中包括replace,replaceAll和replaceFirst。本文将详细讨论这些方法的用法、区别以及示例。1.replace(CharSequencetarget,CharSequencereplaceme......
  • javascript url 传递参数中文乱码问题解决方案
    在JavaScript中,传递URL参数时,如果参数包含中文字符,可能会出现乱码问题。解决这一问题可以使用encodeURIComponent和decodeURIComponent函数。这些函数会对URL参数进行编码和解码,确保特殊字符(包括中文字符)能够被正确传递和解析。以下是一个完整的解决方案示例: 1.......