不夸张地说,NetPad算是我最近半年在C#开发环境里,用得最值回票价的一个工具。如果你平时写C#,常需要快速验证一段代码逻辑、跑一个临时数据处理脚本、或者查一下数据库里的数据,但又不愿意每次都为了这几行代码去创建一个完整项目,那这个开源的、跨平台的C#编辑器就非常适合你。它本质上是一个基于.NET生态的“即写即运行”脚本环境,类似LINQPad的开源替代品,但做到了Windows、macOS、Linux三端通吃,而且完全免费、代码开源。
我最早知道NetPad,是因为关注了GitHub上的.NET开源项目榜单。当时正好在折腾一个数据清洗的活儿,每次都要开VS建项目、等编译、跑完再清理,来回折腾得心累,于是就开始研究有没有更轻量的方案。试过dotnet-script,也试过直接裸敲dotnet run,都不够顺手,直到把NetPad装起来,第一感觉是:这不就是我一直在找的东西吗。这篇就从一个实际使用者的角度,把这个工具拆开聊一聊——它到底能做什么、怎么用、有哪些优势,又有哪些坑需要注意。
1. NetPad到底是什么,为什么要用它
1.1 它的定位与技术底座
NetPad是一个面向C#开发者的轻量级编辑器,核心定位是“C#脚本即时执行环境”。你用它在空白页面里写几行C#,按一下运行,右侧输出面板直接展示结果,不需要创建工程文件、不需要配置启动项、不需要嗑Main函数,连保存逻辑都比传统IDE省心太多。
从技术层面说,NetPad是构建在.NET最新的技术栈之上的,界面层用了Avalonia这个开源的跨平台UI框架,所以它才能以较低成本实现Windows、Linux、macOS三端一致体验。执行引擎方面,NetPad底层和Roslyn编译服务深度绑定,脚本会经过动态编译后加载执行——这一点和很多“简单包装一下的编辑器”完全不同,它是真正实现了“编译-运行”闭环的。
1.2 它解决了什么实际问题
不爱用传统项目结构来跑临时代码的人,基本都能GET到NetPad的价值。拿我自己常见的几个场景来说:
- 验证一个正则表达式是否匹配预期文本
- 快速测试某个NuGet包的API调用方式
- 从Excel读取数据,做分组统计,再导出结果
- 连接开发库,执行查询,对返回结果做二次加工
- 临时算一组算法结果,比如排序、去重、模拟数据
这些场景如果用传统方式做,要么得新建控制台项目并在临时文件里堆代码,要么得打开单元测试项目写测试方法,要么就得切到命令行去执行SQL。NetPad把这些全部装进一个窗口,文件打开就能写,写完就运行,还能保存成脚本反复使用。对我这种经常做数据核对和接口联调的人来说,效率提升不是一点半点。
1.3 和主流竞品的横向对比
说到C#脚本工具,很多人第一个想到的是LINQPad。LINQPad确实非常强大,尤其它的Dump功能堪称神器,但问题是它高级功能都要靠收费授权解锁,并且跨平台体验一直不太顺畅。NetPad作为开源方案,最大的优势是免费、跨平台、代码透明,你甚至可以直接去GitHub上看它的源码实现。
如果和dotnet-script这种命令行工具比,NetPad的图形界面、表格化输出、数据库连接管理又是压倒性的优势。dotnet-script适合极客式的CLI流,但要在上手成本、可视化反馈、工程化管理几个维度综合打分,NetPad绝对更贴近普通开发者的使用习惯。
2. 安装和跨平台环境准备
2.1 Windows、macOS、Linux三平台安装差异
NetPad的安装分发方式比较常规,Windows平台的exe安装包、macOS的dmg镜像、Linux的AppImage包,在GitHub的Releases页面都能找到。根据自己系统下载对应版本就行,这一步基本没难度。
macOS有一点要注意:因为NetPad不是从App Store分发,也没有做Apple官方公证,所以首次打开时会被Gatekeeper拦截。初次使用你需要在“系统设置 -> 隐私与安全性”里手动允许,如果终端打开直接提示“应用已损坏”,多半是隔离属性没删掉:
sudo xattr -dr com.apple.quarantine /Applications/NetPad.appLinux下命令行运行会更直接:
chmod +x NetPad-*.AppImage ./NetPad-*.AppImage如果Linux桌面环境缺依赖导致无法启动,可以先安装libx11相关的运行库,或者用官方提供的命令行安装脚本走一遍,实测Ubuntu和Debian系系统都没问题。
2.2 .NET运行时版本与兼容性细节
NetPad发布时通常会带上自包含的运行时,所以大多数用户不用额外安装.NET SDK也能跑起来。但如果你机器上已经有多版本的.NET环境,建议还是理顺一下版本关系,尤其是NetPad版本升级后,可能要求特定版本的.NET运行时,这时你本地的dotnet环境若低于要求,就很容易出现启动闪退。
我自己遇到过一种情况:机器上装了.NET 6和.NET 8两套SDK,NetPad默认使用环境变量里的dotnet版本加载运行时,结果脚本里引用的NuGet包依赖.NET 8的API,NetPad却一直在旧版本的运行时里执行,导致程序集加载异常。解决办法很简单,检查系统PATH里dotnet的指向,确保NetPad能加载到正确的运行时版本。
2.3 工作区和项目文件组织
NetPad和VS Code类似,也有“工作区”的概念。你可以把脚本按项目或按用途分门别类放进不同的工作区,比如“数据分析”、“接口测试”、“LeetCode刷题”,切换工作区就是切换一套上下文环境。
我的习惯是在本地创建一个专门存放NetPad脚本的目录,用Git做版本管理。这样写过的一些比较通用的脚本片段能留存下来,下次用的时候直接复制或加载,避免重复劳动。NetPad脚本默认以.csx为后缀,本质上是纯文本文件,用任何编辑器都能打开,所以版本控制非常友好。
3. 核心功能拆解与实用场景
3.1 C#脚本如何做到即时执行
NetPad的交互方式很直接:打开脚本,写代码,点运行。它内部处理逻辑大致是:把你写的代码片段包装成一个临时类,动态编译成程序集,再在独立进程里加载运行。你可以在脚本里写表达式,运行结果直接显示,也可以写完整的类、方法、async任务,甚至引用外部包。
一个最简单的表达式脚本:
Enumerable.Range(1, 100).Where(x => x % 3 == 0).Sum()运行后输出面板会显示结果,还可以看到执行用时和内存占用。如果你写的是一段包含输出语句的代码块,比如用Console.WriteLine打印内容,NetPad同样会把这些输出按顺序捕获下来。
还有一个细节,NetPad的脚本支持声明局部函数、定义类型、使用顶级语句和await。这意味着你可以写出类似下面这种比较复杂的逻辑,而不用另外建类库项目:
async Task<string> CallApiAsync(string url) { using var http = new HttpClient(); return await http.GetStringAsync(url); } var data = await CallApiAsync("https://jsonplaceholder.typicode.com/todos/1"); data最后一行data作为表达式结果输出,NetPad会把它格式化成结构化的JSON视图,便于阅读。这种“既能写过程代码又能看结构化结果”的交互方式,比单纯用Console.WriteLine打日志舒服太多。
3.2 数据库连接与查询,比想象中顺手
NetPad对数据库连接的支持是它的加分项之一。它内置了对SQL Server、PostgreSQL、MySQL、SQLite、Oracle等主流数据库的支持。你可以在界面里新建连接,填写连接信息,然后NetPad会把它保存到配置文件中,后续脚本里直接通过某只“内置对象”访问数据库。
以SQLite为例,新建连接时选择“SQLite”,指定数据库文件路径后,脚本里可以直接执行SQL查询并把结果集以表格形式展示:
Db.Query("SELECT * FROM products WHERE price > @price", new { price = 100 })注意这里的Db对象是NetPad注入的全局上下文,无需手动打开连接或做太多管道工作。执行结果会直接在输出面板里渲染成表格,还可以一键转成JSON格式查看。对经常做数据核对的开发者来说,这意味着你可以用C#和SQL混合操作数据,查询结果出来以后直接用LINQ做二次处理,整个流程非常顺畅。
不过有一点要提醒:数据库连接虽然方便,但NetPad本质是开发调试工具,不是生产级数据库管理客户端。生产环境的连接串最好还是单独保护,不要保存到公共工作区的配置文件里,安全第一。
3.3 NuGet包引用,实现脚本级复用
NetPad支持直接在脚本中引用NuGet包。有GUI操作方式,在右侧“引用”面板搜索包并添加即可,之后NetPad会自动添加对应的指令到脚本头部。如果你更喜欢直接编辑脚本,可以手动写引用指令:
#r "nuget: Newtonsoft.Json, 13.0.3"添加后,脚本里就能直接使用Newtonsoft.Json的API。这个能力极大扩展了脚本的功能边界:需要解析Excel?引入ExcelDataReader;需要操作Word?引入OpenXML;需要做HTTP请求?System.Net.Http已经内置,直接using就能用。
我自己有一个常用的“万能模板”脚本,里面预置了我最常用的几个包引用和辅助函数,比如ClosedXML处理Excel、Dapper操作数据库、NodaTime处理时间。每次新建脚本,基于这个模板开始写,绝大多数场景都能直接覆盖,再也不用为了一个小功能去创建完整项目。
3.4 多文件脚本加载,复杂逻辑也能拆分
早期NetPad只支持单文件脚本,后面的版本已经加入了多文件加载机制。你可以把公共代码放到单独的.csx文件里,再在主脚本中通过#load指令引入:
#load "common/Extensions.csx" #load "common/Database.csx"这种方式很适合组织稍微复杂一点的临时工具。比如我写过一个小系统,从某个外部接口拉取数据,做清洗转换,再批量灌入数据库。整个逻辑拆成了三个文件:接口请求封装、数据清洗扩展方法、主流程脚本。如果挤在一个文件里,会超过五百行,调试起来很费劲;拆成模块后,哪个环节出问题,直接定位那个文件就行。
要注意,被#load进来的脚本里的using和#r指令在主脚本编译时是共享上下文的,所以不同文件里不要重复定义同名的类和扩展方法,否则会出现二义性错误。这个和C#编译项目的引用逻辑有些差异,刚上手的人容易踩。
4. 实操记录:用NetPad完成一次真实的数据处理任务
4.1 任务背景与方案拆解
有一次运营部门丢给我一张Excel表,里面是上万条用户注册明细,要求按注册渠道和城市做交叉统计,最后输出一份带排名的统计表。传统方案是用Excel透视表,但数据量一上万,Excel操作就开始卡,而且这种统计每周都要做一次,不能一直靠人工处理。
我决定用NetPad来写一个可重复执行的脚本。方案拆解如下:
- 用ExcelDataReader读取.xlsx文件
- 用LINQ做分组聚合
- 用ClosedXML生成结果Excel
- 统计数据输出到NetPad面板,同时保存文件
4.2 具体实现与运行过程
首先在脚本顶部添加NuGet包引用:
#r "nuget: ExcelDataReader" #r "nuget: ExcelDataReader.DataSet" #r "nuget: ClosedXML" using System.Text; using System.Data; using ExcelDataReader; using ClosedXML.Excel;然后注册编码提供者,这点非常关键。ExcelDataReader在读取中文字符时依赖正确的编码注册:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);接下来读取Excel:
using var stream = File.OpenRead("用户注册明细.xlsx"); using var reader = ExcelReaderFactory.CreateReader(stream); var ds = reader.AsDataSet(); var dt = ds.Tables[0];然后写分组统计逻辑:
var rows = dt.Rows.Cast<DataRow>(); var stats = rows .GroupBy(r => new { City = r["城市"]?.ToString(), Channel = r["注册渠道"]?.ToString() }) .Select(g => new { g.Key.City, g.Key.Channel, Count = g.Count() }) .OrderByDescending(x => x.Count) .ToList();最后把结果输出到新Excel:
using var wb = new XLWorkbook(); var ws = wb.Worksheets.Add("统计结果"); ws.Cell(1, 1).Value = "城市"; ws.Cell(1, 2).Value = "注册渠道"; ws.Cell(1, 3).Value = "数量"; for (int i = 0; i < stats.Count; i++) { ws.Cell(i + 2, 1).Value = stats[i].City; ws.Cell(i + 2, 2).Value = stats[i].Channel; ws.Cell(i + 2, 3).Value = stats[i].Count; } wb.SaveAs("统计结果.xlsx");脚本运行总共耗时不到三秒,NetPad输出面板里还直接列出了统计结果的前几条记录预览。和以前在Excel里操作半个小时、结果还不一定正确相比,这个效率可以说是碾压级的。之后的每周统计,只需要把新表覆盖到同样路径,运行一下脚本就能拿到结果,连公式都不用重新设计。
4.3 这个案例带来的体会
做完这个任务,我最大的感受是:NetPad解决的关键问题不是“运行C#代码”这件事本身,而是把“从想法到结果”的距离压缩到了最短。以前写工具会纠结要不要建项目、要不要考虑程序集结构,现在完全不需要,打开就是干。任务做完,脚本文件留档,下次复用或改造都极其方便。
5. 常见问题排查与避坑记录
5.1 高频问题速查表
我在使用过程中积累了一些常见问题和解决方案,整理成表,方便大家直接参考:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 启动时闪退,无错误提示 | 本地.NET运行时版本与NetPad要求不一致 | 检查PATH变量中dotnet版本,或安装NetPad要求的运行时版本 |
| 脚本引用NuGet包后编译报错 | 包版本冲突或目标框架不兼容 | 在引用指令中明确指定包版本;检查包是否支持当前.NET版本 |
| ExcelDataReader读取中文乱码 | 未注册编码提供程序 | 先执行Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) |
| 数据库连接超时 | 长时间未操作,连接池断开 | 在脚本中重新获取连接,或检查数据库网络策略 |
| 输出面板结果太长被截断 | 默认输出长度限制 | 在设置里调整输出限制,或改用文件方式导出结果 |
| Linux下无法启动 | 缺少系统依赖库 | 安装libx11、libice等基础库,尝试AppImage与命令行包两种方式 |
5.2 避坑心得和调试技巧
有几个经验,是用了很久才慢慢体会到的,这里专门分享出来。
第一,NetPad的脚本文件虽然叫.csx,但它对顶层语句的处理方式和纯C#脚本工具不完全一样。如果你从别的地方复制一段带顶层using namespace的代码进来,大概率会编译失败。NetPad更倾向于脚本头部用#r和#load做引用,正文直接写代码,不要把完整.Program结构搬进来。
第二,做数据库查询时,Db.Query方法返回的结果集在输出面板里展示很友好,但如果结果集特别大,比如几万行,面板渲染会卡顿。这种场景最好在脚本里主动Limit一下,或者在SQL里用TOP/limit子句限制返回条数,只把必要的数据拉到内存处理。
第三,如果你脚本里使用了HttpClient,一定要记得用完释放掉。NetPad虽然运行在独立的进程环境里,但如果脚本长期运行或者频繁执行,不释放连接资源会占用大量socket端口,最终影响本机网络连接。
第四,NetPad的NuGet缓存目录和Visual Studio的全局NuGet缓存是公用的。如果你在VS里清过缓存,NetPad这边的引用也可能需要重新解析。此时可以到NetPad设置里清理一次本地NuGet缓存并重新加载。
5.3 脚本运行效率的小优化
NetPad脚本本质上是动态编译,首次执行会比传统的预制项目慢一些,因为它要经历编译和加载。如果你的脚本很复杂、引用了大量NuGet包,首次运行的耗时可能在几秒到十几秒之间,这属于正常现象。但如果你发现同一个脚本每次执行都非常慢,可以检查是不是有数据库连接或文件I/O拖了后腿,必要时在脚本里做结果缓存,减少重复查询。
6. 跨平台体验与实际应用场景再延伸
6.1 在不同系统上的日常使用感受
我在macOS和Windows上都用NetPad写过代码。macOS上的界面渲染流畅度不错,中文输入法也兼容良好,整体感觉和原生应用没太大差别。Windows上的体验则更“稳”,毕竟.NET生态在Windows上是主场,文件关联、右键菜单这类小功能都更加顺滑。Linux我没作为主力开发环境用过,但在Ubuntu虚拟机里测试过,能正常安装、运行和连接SQLite数据库,对Linux党来说已经够用。
要说有什么不足,就是NetPad在UI美学上还是有点偏“工程师审美”,不如一些商业化IDE精致。但对工具类应用来说,效率和功能永远排在第一位,界面简洁反而是加分项。
6.2 可以配合使用的周边工具
NetPad本身定位是轻量脚本环境,如果你需要更完整的项目开发体验,可以把它和VS Code、Rider或Visual Studio结合使用。我的工作流是:项目开发用VS Code/Rider,临时脚本和数据处理用NetPad,两边通过Git仓库共享代码和脚本文件。这样既不影响正式项目的工程质量,又不牺牲临时任务的灵活性。
另外,NetPad脚本可以当作一种“代码笔记”来用。我在学习一个新的NuGet库时,会专门建一个脚本文件,把手册里的示例代码跑一遍,再改成自己需要的参数,最后留下一份带注释的可用脚本。相当于给自己维护了一份可执行的API知识库,比单纯收藏文档链接实用太多。
7. 一些个人感想与后续玩法建议
如果你也经常面对“为跑几行代码建一个工程”的尴尬,NetPad大概率能帮你解脱出来。我在实际使用中最深的体会是:一个顺手的工具,本质上是在帮你降低“开始做事”的心理门槛。以前面对一个小需求,光是创建项目、等编辑器加载、配置命名空间就要花掉不少耐心,现在打开NetPad十秒内就能跑起来,这种即时反馈的感觉非常舒服。
最后想分享一个扩展玩法:把NetPad脚本作为自动化小工具的一部分。比如配合系统定时任务,定期执行一个数据汇总脚本,把结果输出到固定路径,再由其他流程去消费。当然,NetPad本身不是为无人值守服务设计的,这里只是提供一个思路——它的脚本能力足够灵活,能干很多超出“编辑器”三个字预期的事情。
工具毕竟是工具,重要的是怎么利用它解决自己手头的问题。NetPad在过去一年多里帮我省下了大量搭建临时项目的时间,也希望这篇文章能帮你省下一些摸索的成本。如果你也有关于NetPad的神仙用法或者踩坑经历,欢迎在评论区一起交流。