首页/新闻资讯/正文详情

Csharp快速上手(框架搭建+实战:矩阵卷积计算)

发布时间:2026/9/24 17:18:52 来源:云帆数科 栏目:资讯中心
Csharp快速上手(框架搭建+实战:矩阵卷积计算)
1.基础控件1.1 工具箱——集成各种控件控件在视图底下的工具箱1.2 ToolStrip控件——菜单栏这里主要说Button按钮正常点击是这个样子 只有图片 没有文字 右键 打开属性选择ImageAndTextImage里可以更改图片 Text里可以改文字1.3 OpenFileDialog打开文件我们现在把之前创建的Button新增一个打开文件的功能我们这里给控件改一个名字双击Button会自动跳转到代码界面 我们可以将点击这个Button后触发的事件写进这里面同时Button控件也新增了一个事件如果要删除Button的点击效果 我们要从事件里面删除开始编写代码这是 C# WinForms 中OpenFileDialog组件的标准交互逻辑弹出文件选择对话框当用户点击「确定OK」按钮后执行{ }内的业务代码代码运行效果如下 不过此刻打开后不会发生任何情况 因为{}里面什么东西都没有我们先写一些基础代码操作获取选中的文件路径private void OpenFile_Click(object sender, EventArgs e) { if (openFileDialog1.ShowDialog() DialogResult.OK) { string filePath openFileDialog1.FileName; // 弹出系统对话框显示文字内容 MessageBox.Show($选中的文件路径{filePath}, 文件选择成功); } }运行效果1.4 SaveFileDialog保存文件SaveFileDialog是 WinForm 框架提供的系统原生「另存为」对话框组件它的作用是为用户提供可视化的保存路径选择、文件名输入、文件类型切换界面最终将用户选定的完整文件路径返回给程序。它本身不执行文件写入实际保存逻辑需要开发者通过文件 IO 代码实现。同样的操作我们来新建一个Button 并重命名为SaveFile我们来创建一个点击事件 并编写代码private void SaveFile_Click(object sender, EventArgs e) { if(saveFileDialog1.ShowDialog()DialogResult.OK) { string filePath saveFileDialog1.FileName; if(filePath!null) { } } }运行效果点击确定后 不会有任何事情发生 因为我们的代码里什么都没写1.5 RichTextBox展示与编辑文本RichTextBox是 WinForm 中的高级文本编辑控件支持字体 / 颜色 / 字号格式化、段落排版、嵌入图片、超链接识别等富文本功能能力远强于普通TextBox。从工具箱拖入窗体后默认名称为richTextBox1常用于实现文本编辑器、日志展示、富文本文档查看等场景。现在其实我们就可以根据这几个控件编写一个小程序private void OpenFile_Click(object sender, EventArgs e) { if (openFileDialog1.ShowDialog() DialogResult.OK) { string filePath openFileDialog1.FileName; if(filePath ! null) { richTextBox1.Text filePath; } } } private void SaveFile_Click(object sender, EventArgs e) { if(saveFileDialog1.ShowDialog() DialogResult.OK) { string filePath saveFileDialog1.FileName; if(filePath!null) { var writer new StreamWriter(filePath); writer.WriteLine(richTextBox1.Text); writer.Close(); } } }1. OpenFile_Click —— 打开文件按钮事件点击对应按钮后会弹出系统标准的「打开文件」对话框若用户在对话框中选中文件并点击「确定」会获取该文件的完整路径将这个文件路径字符串直接显示在richTextBox1富文本框中该方法不会读取文件里的实际内容仅展示路径。2. SaveFile_Click —— 保存文件按钮事件点击对应按钮后会弹出系统标准的「保存文件」对话框若用户在对话框中选择保存位置、输入文件名并点击「确定」会得到目标保存路径创建StreamWriter文件写入流把richTextBox1里当前的全部文本内容写入到该路径的文件中写入完成后调用Close()手动关闭文件流。运行效果代码这里 说一下写入方法Write和WriteLine是TextWriterStreamWriter的基类的核心写入方法唯一本质区别是写入完成后是否自动追加换行符其他重载规则、支持的数据类型完全一致。1. Write () 方法行为仅将指定内容字符串、字符、数字等写入流不添加任何额外字符。效果写入内容完全精确不会凭空多出换行、空格。适用场景需要严格匹配原始内容、手动控制换行、拼接文本的场景。2. WriteLine () 方法行为写入指定内容后自动在末尾追加一个系统默认换行符Windows 环境下是\r\n对应Environment.NewLine。特殊用法不带参数的WriteLine()效果是只写入一个换行符。适用场景逐行写入日志、按行输出内容需要自动换行的场景。var writer new StreamWriter(filePath);1.var—— 隐式类型推断关键字var是 C# 的语法糖作用是让编译器根据等号右边的表达式自动推导出变量的具体类型不用手动写出完整类型名。这里右边是new StreamWriter(...)所以编译器会自动推断writer的类型就是StreamWriter。它和手写StreamWriter writer new StreamWriter(filePath);完全等价编译后没有任何区别也不影响性能。2.writer—— 变量名就是你给这个StreamWriter对象起的名字通过它你才能后续调用写入、关闭等方法比如writer.Write()、writer.Close()。3.new StreamWriter(filePath)—— 核心功能本体这才是真正创建文件写入能力的部分StreamWriter是 .NET 中System.IO命名空间下的类专门用来以文本形式向文件写入字符数据。new StreamWriter(filePath)会做两件事打开你指定路径的文件如果文件不存在就自动创建如果文件已存在默认会清空并覆盖原有内容。在内存和文件之间建立一个 “写入流通道”后续你调用写入方法时数据会通过这个通道写到磁盘文件里。2.我个人喜欢的界面风格上面那些基础控件会了之后 我们其实就能做不少基础的程序 无非就是写写算法 读取数据之类的麻烦一点罢了 但我认为一个好的程序 它的界面也要比较好看2.1 StatusStrip状态栏控件这个控件功能比较多 但程序不复杂的时候可以当个花瓶用用StatusLabel2.2 SplitContainer 分割容器控件核心说明基础功能它会将一块完整的显示区域拆分为两个独立的子面板Panel1与Panel2中间带有一条可拖拽的分隔条用户可以自由拖动分隔条调整两个面板的尺寸占比两个面板内部都可以独立嵌套放置其他控件。布局特性支持两种分割方向Vertical垂直分割左右双面板、Horizontal水平分割上下双面板。支持停靠Dock填充常作为窗体主布局容器自动适配窗口大小变化。可通过属性锁定分隔条、设置分隔条宽度、定义最小面板尺寸避免面板被拖拽到过小。布局效果2.3 GroupBox 分组框控件基础功能它的核心作用是为一组功能关联的控件提供带标题的边框容器从视觉和逻辑上对界面控件进行分组归类让用户能直观区分不同功能区域避免界面控件杂乱。主要特性属于容器控件内部可嵌套放置文本框、单选框、按钮等任意子控件移动 GroupBox 时内部控件会同步位移方便批量布局管理。通过Text属性自定义分组标题比如 “基本信息”“高级设置”也可调整边框样式、字体、背景色匹配整体界面风格。常和单选按钮RadioButton配合使用同一个 GroupBox 内的单选按钮会自动形成一组互斥选项。效果展示这里我们说一下Dock这个功能Dock属性选择Fill 可以填满父容器改个名字 调个色BackColor插入RichTextBox后界面整体大概就是这样当然一般我是以表格的形式去呈现原始数据的 这以后再说3.实战一矩阵卷积计算3.1 Matrix.cs我觉得要先构建一个矩阵数据结构新建一个文件 专门用来构建Matrixnamespace WindowsFormsApp2 { internal class Matrix { public double[,] data; public Matrix() { data new double[,] { }; } } }这段是 C# 语言编写的代码归属于 WindowsFormsApp2 这个命名空间定义了一个仅在当前项目内部可用的 Matrix 矩阵类。命名空间的作用是对代码进行分类组织避免不同模块的类名出现冲突。类前面的 internal 是访问修饰符代表这个 Matrix 类只能在当前这个 WinForm 项目编译生成的程序集内部被访问使用外部项目引用时无法调用这个类。类内部定义了一个 public 修饰的二维双精度浮点型数组字段 data它是这个矩阵类的核心数据载体用来存放矩阵里的所有数值元素。接下来的 public Matrix () 是这个类的无参构造函数每当我们创建一个新的 Matrix 对象时这个方法就会自动执行它的作用是对 data 字段进行初始化在对象创建时默认给 data 赋值为一个长度为 0 的空二维数组让新生成的矩阵实例初始处于空数据的状态。内置一个求和函数Sum()在Matrix类里面public double Sum() { double result 0; for(int i0; idata.GetLength(0); i) { for(int j0; jdata.GetLength(1); j) { result data[i,j]; } } return result; }完整代码internal class Matrix { public double[,] data; public Matrix() { data new double[,] { }; } public double Sum() { double result 0; for(int i0; idata.GetLength(0); i) { for(int j0; jdata.GetLength(1); j) { result data[i,j]; } } return result; } }3.2 FileHelper.cs用于帮助读取文档 并将读取结果转换到我们的Matrix数据结构public static double[,] ReadM(string filePath) { int n 3; var Result new double[3,3]; var readernew StreamReader(filePath); try { for (int i 0; i n; i) { string data reader.ReadLine(); for (int j 0; j 3; j) { var buf data.Split(\t); Result[i,j]double.Parse(buf[j]); } } } catch (Exception ex) { throw ex; } reader.Close(); return Result; } public static double[,] ReadN(string filePath) { int n 10; var Result new double[10, 10]; var reader new StreamReader(filePath); try { for (int i 0; i n; i) { string data reader.ReadLine(); for (int j 0; j n; j) { var buf data.Split(\t); Result[i, j] double.Parse(buf[j]); } } } catch (Exception ex) { throw ex; } reader.Close(); return Result; }这个代码很粗糙 而且复用性很差 只能针对一种特殊的数据结构矩阵每一行相邻俩个元素以制表符分隔开来 但方便理解这里说一下Read和ReadLine 1. ReadLine 实现 ReadM 读取矩阵 矩阵维度3行 × 3列 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 2. ReadLine 逐行读取原始效果 第1行[1.1 2.2 3.3]文本长度9 第2行[4.4 5.5 6.6]文本长度9 第3行[7.7 8.8 9.9]文本长度9 读到文件末尾返回 null 3. Read 逐字符读取原始效果 第1个字符[1]ASCII码49 第2个字符[.]ASCII码46 第3个字符[1]ASCII码49 第4个字符[空格]ASCII码32 第5个字符[2]ASCII码50 第6个字符[.]ASCII码46 第7个字符[2]ASCII码50 第8个字符[空格]ASCII码32 第9个字符[3]ASCII码51 第10个字符[.]ASCII码46 第11个字符[3]ASCII码51 第12个字符[\r]ASCII码13 第13个字符[\n]ASCII码10 第14个字符[4]ASCII码52 ...中间字符省略 第38个字符[9]ASCII码57 第39个字符[.]ASCII码46 第40个字符[9]ASCII码57 读到文件末尾返回 -1接下来我们可以直接写算法了 可以先直接跳转到3.3 Algo.cs看完算法的设计后 我们应该做的是读取数据——计算——输出结果编写结果输出代码public static string WriteData(Matrix m) { string Result ; for (int i 0; i m.data.GetLength(0); i) { for (int j 0; j m.data.GetLength(1); j) { Result Result m.data[i, j].ToString() \t; } Result Result \n; } return Result; }这里是将我们读取的数据转换为字符串public static string WriteResult(Matrix m) { string Result ; for (int i 0; i m.data.GetLength(0); i) { for (int j 0; j m.data.GetLength(1); j) { Result Result ${m.data[i,j]:f2}\t; } Result Result \n; } return Result; }这里我们将计算结果转换为字符串3.3 Algo.cs只实现算法1internal class Algo { public double[,] Algo1(Matrix M, Matrix N) { var Result new double[10, 10]; for(int i0;iN.data.GetLength(0);i) { for(int j0;jN.data.GetLength(1);j) { Result[i, j] InAlgo1(i, j, M, N); } } return Result; } public double InAlgo1(int I, int J, Matrix M, Matrix N) { double Result 0; int i_e 3; int j_e 3; double Mij 0; double Nij 0; double sum1 0;//分子 double sum2 0;//分母 for (int i 0; i i_e; i) { for (int j 0; j j_e; j) { if (I - i - 1 0 || J - j - 1 0 || I - i - 1 9 || J - j - 1 9) { Mij 0; } else { Mij M.data[i, j]; Nij N.data[I-i-1, J-j-1]; } sum1 sum1 Mij * Nij; sum2 sum2 Mij; } } Result sum1 / sum2; return Result; } }只要把算法的公式搞懂 对着敲代码就行 这里介绍俩个知识点data.GetLength(0)和data.GetLength(1data.GetLength(0)获取矩阵的行数。data.GetLength(1)获取矩阵的列数。var Result new double[10, 10];还有这个地方要强调一下这里不能像定义Matrix类一样 初始定义一个0行0列的二维矩阵必须要申明申请的空间大小不然访问时会说数组超限3.4 框架到这一步 我们就像拼一个机器人 现在已经把各个零件都拼好了 现在就是组装还记得我们的OpenFile_Click吗 现在我们要开始做些手脚了在做手脚前 我们先弄一下框架完整代码using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp2 { public partial class Form1 : Form { Matrix M new Matrix(); Matrix N new Matrix(); Matrix Result new Matrix(); string data ; public Form1() { InitializeComponent(); } private void OpenFile_Click(object sender, EventArgs e)//读取M矩阵 { if (openFileDialog1.ShowDialog() DialogResult.OK) { string filePath openFileDialog1.FileName; if(filePath ! null) { M.data FileHelper.ReadM(filePath); } data FileHelper.WriteData(M); richTextBox1.Text data; } } private void SaveFile_Click(object sender, EventArgs e)//保存文件 { if(saveFileDialog1.ShowDialog() DialogResult.OK) { string filePath saveFileDialog1.FileName; if(filePath!null) { } } } private void toolStripStatusLabel1_Click(object sender, EventArgs e) { } private void panel1_Paint(object sender, PaintEventArgs e) { } private void toolStripButton1_Click(object sender, EventArgs e)//读取N矩阵 { if (openFileDialog1.ShowDialog() DialogResult.OK) { string filePath openFileDialog1.FileName; if (filePath ! null) { N.data FileHelper.ReadN(filePath); } data FileHelper.WriteData(N); richTextBox1.Text data; } } private void toolStripButton2_Click(object sender, EventArgs e)//计算 { var algo new Algo(); Result.data algo.Algo1(M, N); richTextBox2.Text FileHelper.WriteResult(Result); } } }这里我们还没写文件保存的代码其实可以类推一下读取文件var Reader new StreamReader(filePath);同理var Writer new StreamWriter(filePath);private void SaveFile_Click(object sender, EventArgs e)//保存文件 { if(saveFileDialog1.ShowDialog() DialogResult.OK) { string filePath saveFileDialog1.FileName; if(filePath!null) { var writer new StreamWriter(filePath); writer.Write(richTextBox2.Text); writer.Close(); } } }运行结果如下

相关推荐

今天8时05分,秋天被按下“平分键”:关于秋分,很多人理解错了
今天8时05分,秋天被按下“平分键”:关于秋分,很多人理解错了

今天8时05分,我们迎来秋分。 太阳运行至黄经180度,直射点来到赤道附近。此后,北半球的白昼将继续缩短,黑夜逐渐变长,秋天正式走到中段。 但秋分真的意味着昼夜各12小时吗?全国都会从今天开始降温吗&#xf… · 2026/9/24 17:18:52

xLua 核心 API 全解析:从 C 调用 Lua 到类型映射与内置宏
xLua 核心 API 全解析:从 C 调用 Lua 到类型映射与内置宏

xLua 核心 API 全解析:从 C# 调用 Lua 到类型映射与内置宏 【免费下载链接】xLua xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. 项目地址: https://gitcode.com/gh_mirrors/xl/xLua … · 2026/9/24 17:18:52

Reason 内置的 OCaml Migrate Parsetree(vendored-omp):跨 OCaml 版本解析与 PPX 迁移的完整指南
Reason 内置的 OCaml Migrate Parsetree(vendored-omp):跨 OCaml 版本解析与 PPX 迁移的完整指南

编程语言编译器 【免费下载链接】reason Simple, fast & type safe code that leverages the JavaScript & OCaml ecosystems 项目地址: https://gitcode.com/gh_mirrors/re/reason 点击查看 免费下载 本篇技术指南围绕 reason 仓库中内置的 vendored-omp&… · 2026/9/24 17:18:52

PyTorch CNN手写数字识别:从MNIST训练到Tkinter GUI部署
PyTorch CNN手写数字识别:从MNIST训练到Tkinter GUI部署

简介:面向计算机专业学生,提供一份基于卷积神经网络在MNIST数据集上实现手写数字识别的Python源码项目,附带GUI交互界面,适合作为毕业设计、课程设计或深度学习入门的实战参考。整个压缩包共23个项目文件,体积仅3.53MB… · 2026/9/24 18:24:10

.NET直播流媒体服务器Berry.Live实战:从部署到调优
.NET直播流媒体服务器Berry.Live实战:从部署到调优

做直播服务端选型这件事,我前前后后折腾过不少方案。从最早用Nginx加RTMP模块自己拼,到后来上SRS,再到换Go写的轻量服务,每个方案都有让人挠头的地方。最近一段时间我一直在用Berry.Live这套基于.NET的直播流媒体服务器&#xff0… · 2026/9/24 18:24:10

本地AI应用的三大安全边界:SQLite、Tauri IPC与FastAPI环回风险
本地AI应用的三大安全边界:SQLite、Tauri IPC与FastAPI环回风险

1. 为什么“本地运行”不等于“绝对安全”:从VoiceStudio的架构真相说起 很多人看到“本地语音AI”四个字,第一反应就是:数据不出设备、没联网、肯定零风险。我去年在给一家医疗语音录入系统做安全审计时,也这么想——直到我们用T… · 2026/9/24 18:24:10

云计算技术人变现指南:12条可落地的副业与创业路径
云计算技术人变现指南:12条可落地的副业与创业路径

最近总有人在社群里问我同一个问题:做云计算这行,技术学了不少、项目也做了不少,但感觉收入天花板就在那,除了跳槽涨薪,还有没有别的路子?我直接说结论:云计算技术人的变现路径,远比… · 2026/9/24 18:24:10

Java在线教育平台6.2源码解析与部署实战:从跑通到二次开发避坑指南
Java在线教育平台6.2源码解析与部署实战:从跑通到二次开发避坑指南

简介:基于Java技术的在线教育平台6.2版本设计源码是一套面向教育行业开发者与学习者的完整工程,适用于在线课程管理、视频教学、在线考试、作业提交等业务场景,能够帮助理解微服务与数据仓库相结合的后端架构实现。压缩包共69个文件&#xff… · 2026/9/24 18:24:10

VSCode 高效配置指南:从环境搭建到远程开发与 AI 编程
VSCode 高效配置指南:从环境搭建到远程开发与 AI 编程

最近后台好多朋友都在问 VSCode 的玩法,从最基础的安装汉化,到配 C/C、Python,再到 Git、SVN、远程 SSH,还有一批追新的人开始折腾 Codex、OpenCode、DeepSeek 这类 AI 插件。我干脆把这一年多来实际用 VSCode 干活时沉淀下来的操… · 2026/9/24 18:24:04

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码