(for 循环) VS (LINQ) 性能比拼 ——c#

news2025/5/17 5:46:36

在大多数情况下,for 循环的原始性能会优于 LINQ,尤其是在处理简单遍历、数据筛选或属性提取等场景时。这是由两者的实现机制和抽象层次决定的。以下是具体分析:

一、for 循环与 LINQ 的性能差异原因

1. 抽象层次与执行机制
  • for 循环
    命令式编程的直接实现,通过索引直接操作集合,代码逻辑在编译后直接转化为底层循环指令(如 forwhile 等),无额外中间层开销
  • LINQ
    声明式编程,基于泛型委托(如 Func<T, bool>)和迭代器(IEnumerator)实现。每次调用 WhereSelect 等方法时,会创建延迟执行的表达式树或委托链,执行时需要频繁调用委托(Invoke)或迭代器方法(MoveNext()),引入额外的方法调用开销
2. 内存与缓存友好性
  • for 循环
    通常使用索引访问(如 cursall[i]),内存访问模式更连续,利于 CPU 缓存优化,尤其适合数组或实现了 IList<T> 的集合(如 List<T>)。
  • LINQ
    对集合的访问可能更 “抽象”,例如通过 foreach 遍历或迭代器,虽然本质上也是索引访问,但底层可能涉及更多间接操作(如 IEnumerator<T>.Current 属性),缓存利用率可能略低。
3. 编译优化空间
  • for 循环
    结构简单,编译器更容易进行循环展开分支预测优化等低级优化,减少 CPU 流水线阻塞。
  • LINQ
    由于基于委托和泛型,编译器难以对其内部逻辑做深度优化,尤其是动态创建的委托链可能导致更多的虚方法调用(如 Func<T>.Invoke),增加开销。

二、结合具体场景分析

例如下面例子,for 循环的核心操作是:

遍历集合 cursall,获取每个元素的 GeometricExtentsExtents3d bbox = cursall[i].GeometricExtents)。

  1. 筛选非空 bbox 并存储到 有效包围盒 列表中。

如果注释掉这段 for 循环,后续可能通过 LINQ 实现类似逻辑(例如用 cursall.Where(x => x != null).Select(x => x.GeometricExtents).Where(bbox => bbox != null)),此时性能差异的原因可能是:

1. LINQ 的多重遍历与委托开销
  • LINQ 的 Where 和 Select 是延迟执行的,每次调用都会生成新的迭代器。例如:

    csharp

    // 等效 LINQ 逻辑(假设 cursall 是 List<Curve>)
    var 有效包围盒 = cursall
        .Where(x => x != null)
        .Select(x => x.GeometricExtents)
        .Where(bbox => bbox != null)
        .ToList();
    

    这段代码会对 cursall 进行三次隐式遍历(每次 Where/Select 都会触发一次迭代),每次遍历都需要调用委托(如 x => x != null),而 for 循环只需一次遍历即可完成筛选和存储。
2. 避免重复属性访问

在 for 循环中,GeometricExtents 只被访问一次,并直接存储结果;而 LINQ 的 Select 可能导致 GeometricExtents 被多次访问(例如若后续操作有多次迭代)。如果 GeometricExtents 是一个计算开销较大的属性(而非简单字段),for 循环的优势会更明显。

三、性能测试建议

若想验证 for 循环与 LINQ 的差异,可以用以下方式测试:

csharp

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

class TestClass {
    public object GeometricExtents { get; set; } // 模拟属性
}

class Program {
    static void Main() {
        var list = Enumerable.Range(0, 1000000).Select(_ => new TestClass()).ToList(); // 大集合
        var count = 0;

        // 测试 for 循环
        var sw = Stopwatch.StartNew();
        var forResult = new List<object>();
        for (int i = 0; i < list.Count; i++) {
            var item = list[i];
            if (item == null) continue;
            var bbox = item.GeometricExtents;
            if (bbox != null) forResult.Add(bbox);
        }
        sw.Stop();
        Console.WriteLine($"For循环耗时:{sw.ElapsedMilliseconds} ms");

        // 测试 LINQ
        sw.Restart();
        var linqResult = list
            .Where(x => x != null)
            .Select(x => x.GeometricExtents)
            .Where(bbox => bbox != null)
            .ToList();
        sw.Stop();
        Console.WriteLine($"LINQ耗时:{sw.ElapsedMilliseconds} ms");
    }
}

典型结果:在百万级数据量下,for 循环通常比 LINQ 快 30%~50%(具体取决于硬件和代码细节)。

四、总结:何时选择 for 循环 vs LINQ?

场景for 循环更优LINQ 更优
简单遍历、性能优先✅ 适合大数据集或高频操作❌ 开销较高
代码简洁性优先❌ 代码冗长✅ 声明式语法更易读
复杂数据转换(如分组、连接)❌ 需要手动实现复杂逻辑✅ 内置方法链简化操作
并行处理❌ 需手动实现并行✅ 可直接用 PLINQ 并行化

你的场景中,由于涉及简单的筛选和属性提取,且性能敏感,for 循环的直接性使其成为更优选择。LINQ 的延迟执行和委托机制在高频操作下会累积明显开销,导致速度变慢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单图像自适应亮度对比度调整

一、背景介绍 继续在刷对比度调整相关算法&#xff0c;偶然间发现了这个简单的亮度/对比度自适应调整算法&#xff0c;做个简单笔记记录。也许后面用得到。 二、自适应亮度调整 1、基本原理 方法来自论文:Adaptive Local Tone Mapping Based on Retinex for High Dynamic Ran…

深入理解二叉树:遍历、存储与算法实现

在之前的博客系列中&#xff0c;我们系统地探讨了多种线性表数据结构&#xff0c;包括顺序表、栈和队列等经典结构&#xff0c;并通过代码实现了它们的核心功能。从今天开始&#xff0c;我们将开启一个全新的数据结构篇章——树结构。与之前讨论的线性结构不同&#xff0c;树形…

【Win32 API】 lstrcmpA()

作用 比较两个字符字符串&#xff08;比较区分大小写&#xff09;。 lstrcmp 函数通过从第一个字符开始检查&#xff0c;若相等&#xff0c;则检查下一个&#xff0c;直到找到不相等或到达字符串的末尾。 函数 int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2); 参数 lpStr…

(C语言)超市管理系统 (正式版)(指针)(数据结构)(清屏操作)(文件读写)

目录 前言&#xff1a; 源代码&#xff1a; product.h product.c fileio.h fileio.c main.c 代码解析&#xff1a; 一、程序结构概述 二、product.c 函数详解 1. 初始化商品列表 Init_products 2. 添加商品 add_product 3. 显示商品 display_products 4. 修改商品 mo…

NAT转换和ICMP

NAT nat原理示意 nat实现 ICMP ICMP支持主机或路由器&#xff1a; 差错或异常报告网络探寻 2类icmp报文&#xff1a; 差错报告报文&#xff08;5种&#xff09; 目的不可达源抑制--拥塞控制超时&超期--TTL超时参数问题--问题报文丢弃重定向--不应该由这个路由器转发&a…

【专利信息服务平台-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

BUUCTF——web刷题第一页题解

共31题&#xff0c;admin那题没有&#xff0c;因为环境问题&#xff0c;我做的非常卡 目录 极客大挑战 2019]Havefun [HCTF 2018]WarmU [ACTF2020 新生赛]Include [ACTF2020 新生赛]Exec [GXYCTF2019]Ping Ping Ping [SUCTF 2019]EasySQL [极客大挑战 2019]LoveSQL [极…

哪个品牌的智能对讲机好用?推荐1款,能扛事更智能

在专业通信领域&#xff0c;智能对讲机早已突破传统设备的局限&#xff0c;成为集通信、调度、数据传输于一体的智能化终端。面对复杂多变的作业环境&#xff0c;用户对设备的稳定性、通信效率和智能化水平提出了更高要求。但是&#xff0c;市面上产品同质化严重&#xff0c;部…

【Win32 API】 lstrcpyA()

作用 将字符串复制到指定的字符串缓冲区。 函数 LPSTR lstrcpyA(LPSTR lpString1, LPCSTR lpString2); 参数 lpString1 类型&#xff1a;LPTSTR 一个缓冲区&#xff0c;用于接收由 lpString2 参数指向的字符串的内容。 缓冲区必须足够大才能包含字符串&#xff0c;包括终止…

Vue3——Watch侦听器

目录 手动指定监听对象 侦听ref对象 侦听ref对象中的某个属性 reactive写法 watchEffect 自动侦听 多源侦听 一次性侦听器 watch 是⼀个⽤于观察和响应Vue响应式系统中数据变化的⽅法。它允许你指定⼀个数据源&#xff08;可以是 响应式引⽤、计算属性、组件的属性等&#xf…

Go的单测gomock及覆盖率命令

安装gomock&#xff1a; go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen 使用 mockgen 生成 mock 代码: 参考 mockgen -sourceservice/user.go -destinationservice/mocks/mock_user_service.go -packagemocks go test -coverprofilecoverage.out…

Leetcode209做题笔记

力扣209 题目分析&#xff1a;想象一个窗口遍历着这个数组&#xff0c;不断扩大右边界&#xff0c;让r。往窗口中添加数字&#xff1a; 此时我们找到了这个窗口&#xff0c;它的和满足了大于等于target的条件&#xff0c;题目让我求最短的&#xff0c;那么我们就尝试来缩短它&…

Suna: 开源多面手 AI 代理

GitHub&#xff1a;GitHub - kortix-ai/suna: Suna - Open Source Generalist AI Agent 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI Suna 是一个完全开源的 AI 助手&#xff0c;可帮助您轻松完成实际任务。通过自然对话&#xff0c…

25-05-16计算机网络学习笔记Day1

深入剖析计算机网络&#xff1a;今日学习笔记总结 本系列博客源自作者在大二期末复习计算机网络时所记录笔记&#xff0c;看的视频资料是B站湖科大教书匠的计算机网络微课堂&#xff0c;每篇博客结尾附书写笔记(字丑见谅哈哈) 视频链接地址 一、计算机网络基础概念 &#xf…

12 web 自动化之基于关键字+数据驱动-反射自动化框架搭建

文章目录 一、如何实现一条用例&#xff0c;实现覆盖所有用例的测试1、结合数据驱动&#xff1a;编辑一条用例&#xff0c;外部导入数据实现循环测试2、用例体&#xff1a;实现不同用例的操作步骤对应的断言 二、实战1、项目路径总览2、common 文件夹下的代码文件3、keywords 文…

动态IP赋能业务增效:技术解构与实战应用指南

在数字化转型加速的今天&#xff0c;IP地址作为网络通信的基础设施&#xff0c;其技术特性正深刻影响着企业业务架构的效率与安全性。动态IP&#xff08;Dynamic IP&#xff09;作为互联网资源分配的核心机制&#xff0c;早已突破传统认知中的"临时地址"定位&#xf…

【Java ee初阶】http(1)

HTTP 全称为“超文本传输协议”&#xff0c;由名字可知&#xff0c;这是一个基于文本格式的协议&#xff0c;而TCP&#xff0c;UDP&#xff0c;以太网&#xff0c;IP...都是基于二进制格式的协议。 如何区别该协议是基于哪种格式的协议&#xff1f; 形如这种协议格式&#xf…

day18-数据结构引言

一、 概述 数据结构&#xff1a;相互之间存在一种或多种特定关系的数据元素的集合。 1.1 特定关系&#xff1a; 1. 逻辑结构 2.物理结构&#xff08;在内存当中的存储关系&#xff09; 逻辑结构物理结构集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等顺…

我开源了一个免费在线工具!UIED Tools

UIED Tools - 免费在线工具集合 最近更新&#xff1a;修改了文档说明&#xff0c;优化了项目结构介绍 这是设计师转开发的第一个开源项目&#xff0c;bug和代码规范可能有些欠缺。 这是一个功能丰富的免费在线工具集合网站&#xff0c;集成了多种实用工具&#xff0c;包括 AI …

什么时候可以开始学习深度学习?

咱们先来聊聊机器学习和深度学习的关系~ 这个问题其实挺常见的&#xff0c;之前我也跟不少同事、同学聊过。最近有好几个同学也聊过。 简单说&#xff0c;深度学习是机器学习的一个子集&#xff0c;两者不是并列关系&#xff0c;而是“包含”关系。 你可以这么理解&#xff…