C# 高效编程指南:从命名空间到异常处理的技巧与最佳实践

在这条成长的路上,有一些核心概念将成为你开发过程中的得力助手—命名空间、预处理指令、正则表达式、异常处理和文件输入输出,这些看似独立的技术,实际上在大多数应用中都紧密相连,共同构成了C#开发的基础。

目录

C#命名空间

C#预处理指令

C#正则表达式

C#异常处理

C#文件输入输出


C#命名空间

        在C#当中命名空间是一个非常重要的概念,它用于组织代码中的类、接口、结构、枚举等类型,通过命名空间可以避免命名冲突并使得代码更加清晰,结构化易于维护,简单来说命名空间就像是一个容器,将相关的代码元素组合在一起以便在较大的项目中进行管理和访问。

        我们举一个计算机系统中的例子,一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名,如下是命名空间的具体作用:

1)避免命名冲突:通过将相似的类或其他类型放入不同的命名空间中避免了命名冲突

2)代码组织可读:帮助将相关的代码逻辑分组从而提高代码的可读性和可维护性

3)简化代码引用:只需要引用命名空间而不必担心类名冲突,特别是当使用大量库或框架时

命名空间:以关键字namespace开始后跟命名空间的名称,Logger类被放在了MyApp.Utilities命名空间中这意味着它属于该命名空间的一部分,如下所示:

namespace MyApp.Utilities
{public class Logger{public void Log(string message){Console.WriteLine(message);}}
}

使用命名:在不同的代码文件中使用命名空间时,我们可以使用using关键字来引用某个命名空间从而避免每次都写完整的命名空间路径,例如:

using MyApp.Utilities;class Program
{static void Main(){Logger logger = new Logger();logger.Log("Hello, World!");}
}

命名嵌套:C#支持命名空间的嵌套,这意味着可以在一个命名空间内部定义另一个命名空间,这样可以进一步帮助细化代码结构,举个例子:

namespace MyApp
{namespace Utilities{public class Logger{public void Log(string message){Console.WriteLine(message);}}}namespace Models{public class User{public string Name { get; set; }}}
}

注意: 命名空间应该反映其包含类型的功能所有应该使用有意义的命名;虽然命名空间可以嵌套但过度嵌套可能导致代码结构复杂难以理解应避免过多的嵌套层次;命名空间应与项目目录结构保持一致这样可以使得项目文件和代码保持一致性。

C#预处理指令

        在C#中预处理指令是一种在编译阶段处理源代码的指令,主要用于控制编译器如何处理代码,这些指令在编译时起作用而不是在运行时,因此它们并不直接影响程序的逻辑而是提供了编译时的控制和灵活性,预处理指令通常用于条件编译、宏定义、代码优化等。下表列出了C#中可用的预处理器指令:

指令描述
#define定义一个符号,可以用于条件编译。
#undef取消定义一个符号。
#if开始一个条件编译块,如果符号被定义则包含代码块。
#elif如果前面的 #if#elif 条件不满足,且当前条件满足,则包含代码块。
#else如果前面的 #if#elif 条件不满足,则包含代码块。
#endif结束一个条件编译块。
#warning生成编译器警告信息。
#error生成编译器错误信息。
#region标记一段代码区域,可以在IDE中折叠和展开这段代码,便于代码的组织和阅读。
#endregion结束一个代码区域。
#line更改编译器输出中的行号和文件名,可以用于调试或生成工具的代码。
#pragma用于给编译器发送特殊指令,例如禁用或恢复特定的警告。
#nullable控制可空性上下文和注释,允许启用或禁用对可空引用类型的编译器检查。

#define和#undef:在下面的例子中,#define DEBUG 定义了一个名为DEBUG的符号,代码中可以使用#if DEBUG来判断这个符号是否已经定义。

#define DEBUG  // 定义DEBUG符号
using System;
class Program
{static void Main(){#if DEBUGConsole.WriteLine("Debug mode is enabled");#endif}
}

#if, #else, #elif, #endif:在下面的代码中,如果定义了DEBUG,则输出"Debugging mode enabled."否则输出 "Production mode."。

#define DEBUG
using System;
class Program
{static void Main(){#if DEBUGConsole.WriteLine("Debugging mode enabled.");#elseConsole.WriteLine("Production mode.");#endif}
}

#warning和#error:在下面这个例子中,#warning会在没有定义FEATURE_X时发出警告,而#error会在没有定义FEATURE_Y时导致编译错误。

#define FEATURE_X
using System;
class Program
{static void Main(){#if !FEATURE_X#warning "Feature X is not enabled. Some functionality may not work."#endif#if !FEATURE_Y#error "Feature Y is required but not defined."#endif}
}

#region和#endregion:用于将代码块包裹起来,使其可折叠帮助开发者整理和管理代码。

#region MyRegion
public void MyMethod()
{Console.WriteLine("Hello, World!");
}
#endregion

使用预处理器指令的注意事项

1)提高代码可读性:使用#region可以帮助分隔代码块,提高代码的组织性。

2)条件编译:通过#if等指令可以在开发和生产环境中编译不同的代码,方便调试和发布。

3)警告和错误:通过#warning和#error可以在编译时提示开发人员注意特定问题。

C#正则表达式

        在C#中正则表达式是一种强大的文本处理工具,用于查找、匹配、替换、验证和操作字符串,通过定义特定的模式来描述字符的匹配规则且这种模式可以被用于各种文本操作,如字符串搜索、数据提取和格式化等。

基本构成:正则表达式由各种字符、符号和元字符组成,常见的正则表达式元素包括:    

类型字符匹配
基本字符a、b、c匹配字符 a、b、c
abc匹配字符串 "abc"
元字符.匹配任意单个字符(除换行符)
^表示匹配字符串的开头
$表示匹配字符串的结尾
[]表示字符集合,匹配其中的任意一个字符
|表示“或”操作,匹配左边或右边的内容
字符类别\d匹配任何数字,相当于 [0-9]
\D匹配任何非数字字符

\w

匹配任何字母、数字或下划线,相当于 [A-Za-z0-9_]
\W匹配任何非字母、非数字、非下划线的字符
\s匹配任何空白字符(空格、制表符、换行符等)
\S匹配任何非空白字符
量词*匹配前面的表达式零次或多次
+匹配前面的表达式一次或多次
?匹配前面的表达式零次或一次
{n}匹配前面的表达式恰好 n 次
{n,}匹配前面的表达式至少 n 次
{n,m}匹配前面的表达式至少 n 次,但不超过 m 次
分组和捕获()将表达式括起来表示一个分组
(?:...)非捕获分组,表示分组但不捕获其内容
\1, \2, \3...表示第1、2、3个捕获组的内容
转义字符\用于转义元字符,使其失去特殊意义,例如 \. 匹配点字符

常见示例

// 匹配邮箱地址:匹配有效的电子邮件地址
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";// 匹配电话号码:匹配如 (123) 456-7890 格式的电话号码
string pattern = @"\(\d{3}\) \d{3}-\d{4}";// 验证日期格式:匹配日期格式为 2024-12-07 的字符串
string pattern = @"^\d{4}-\d{2}-\d{2}$";

在下面这个例子中,使用正则表达式分别查找文本中的电子邮件地址和电话号码,如果找到了匹配项就输出匹配的内容:

using System;
using System.Text.RegularExpressions;class Program
{static void Main(){string input = "My email is john.doe@example.com, and my phone number is (123) 456-7890.";// 正则表达式匹配电子邮件地址string emailPattern = @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}";Match emailMatch = Regex.Match(input, emailPattern);if (emailMatch.Success){Console.WriteLine("Email found: " + emailMatch.Value);}// 正则表达式匹配电话号码string phonePattern = @"\(\d{3}\) \d{3}-\d{4}";Match phoneMatch = Regex.Match(input, phonePattern);if (phoneMatch.Success){Console.WriteLine("Phone number found: " + phoneMatch.Value);}}
}

Regex类:C#提供了一个名为System.Text.RegularExpressions的命名空间,其中包含了处理正则表达式的核心类,最常用的类是Regex类且提供了多种方法来执行正则表达式相关的操作。

Regex类用于创建和处理正则表达式,它主要有以下常用方法:

1)Match():尝试在输入字符串中找到第一个匹配的部分。

2)Matches():查找所有匹配项,并返回一个集合。

3)IsMatch():检查输入字符串是否符合正则表达式。

4)Replace():替换字符串中匹配的部分。

5)Split():根据正则表达式分割字符串。

using System;
using System.Text.RegularExpressions;class Program
{static void Main(){string input = "The price of the book is 30 dollars and the pen costs 5 dollars.";// 正则表达式匹配所有数字string pattern = @"\d+";  // \d+ 匹配一个或多个数字// 使用 Regex.Match() 方法查找第一个匹配Match match = Regex.Match(input, pattern);if (match.Success){Console.WriteLine("Found a match: " + match.Value);}// 使用 Regex.Matches() 方法查找所有匹配MatchCollection matches = Regex.Matches(input, pattern);foreach (Match m in matches){Console.WriteLine("Found a match: " + m.Value);}}
}

C#异常处理

        C#中的异常处理通过try、catch、finally块来管理运行时错误,异常是程序运行时出现的错误通常会导致程序崩溃,使用异常处理可以捕获错误并进行处理能确保程序的稳定性:

try:用来包裹可能发生异常的代码。

catch:用来捕获并处理异常,通常可以根据异常类型进行特定的处理。

finally:无论是否发生异常,都会执行的代码块,通常用于资源清理。

throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。

try
{int result = 10 / 0;  // 这将引发异常
}
catch (DivideByZeroException ex)
{Console.WriteLine("Cannot divide by zero: " + ex.Message);
}
finally
{Console.WriteLine("This will always run.");
}

如果异常是直接或间接派生自System.Exception类可以抛出一个对象,在catch块中使用throw语句来抛出当前的对象,如下所示: 

Catch(Exception e)
{...Throw e
}

C#文件输入输出

        在C#中文件输入输出用于处理文件的读取和写入操作,通过.NET提供的类库可以方便地进行文件操作,如读取文件内容、写入数据到文件、文件复制、删除等,C#中的文件I/O操作主要通过System.IO命名空间下的各种类来实现。

下表列出了一些 System.IO 命名空间中常用的非抽象类:

I/O 类描述
BinaryReader从二进制流读取原始数据。
BinaryWriter以二进制格式写入原始数据。
BufferedStream字节流的临时存储。
Directory有助于操作目录结构。
DirectoryInfo用于对目录执行操作。
DriveInfo提供驱动器的信息。
File有助于处理文件。
FileInfo用于对文件执行操作。
FileStream用于文件中任何位置的读写。
MemoryStream用于随机访问存储在内存中的数据流。
Path对路径信息执行操作。
StreamReader用于从字节流中读取字符。
StreamWriter用于向一个流中写入字符。
StringReader用于读取字符串缓冲区。
StringWriter用于写入字符串缓冲区。

File类提供了静态方法来进行文件的创建、删除、复制、移动、读取、写入等简化了常见的文件操作。

创建文件

using System.IO;string path = "example.txt";
if (!File.Exists(path))
{File.Create(path);  // 创建文件
}

写入文件:File.WriteAllText和File.AppendAllText可用来写入文本到文件中

string path = "example.txt";
string text = "Hello, world!";
File.WriteAllText(path, text);  // 将文本写入文件

读取文件:File.ReadAllText用于读取整个文件的文本内容

string path = "example.txt";
string content = File.ReadAllText(path);  // 读取文件内容
Console.WriteLine(content);

复制文件

string sourcePath = "example.txt";
string destPath = "example_copy.txt";
File.Copy(sourcePath, destPath, true);  // true 表示允许覆盖目标文件

删除文件

string path = "example.txt";
File.Delete(path);  // 删除文件

StreamReader和StreamWriter类提供了更加灵活的文件读取和写入方式,可以逐行读取或写入文本

// 读取文件内容:
using System.IO;
string path = "example.txt";
using (StreamReader reader = new StreamReader(path))
{string content = reader.ReadToEnd();  // 读取整个文件内容Console.WriteLine(content);
}// 逐行读取文件:
using System.IO;
string path = "example.txt";
using (StreamReader reader = new StreamReader(path))
{string line;while ((line = reader.ReadLine()) != null){Console.WriteLine(line);  // 逐行读取并输出}
}// 写入文件内容:
using System.IO;
string path = "example.txt";
using (StreamWriter writer = new StreamWriter(path))
{writer.WriteLine("Hello, world!");  // 写入一行文本
}

FileStream类允许我们以字节流的方式读取和写入文件,对于需要处理大文件或二进制数据时非常有用。

// 读取二进制数据:
using System.IO;
string path = "example.bin";
using (FileStream fs = new FileStream(path, FileMode.Open))
{byte[] data = new byte[fs.Length];fs.Read(data, 0, data.Length);  // 读取二进制数据
}// 写入二进制数据:
using System.IO;
string path = "example.bin";
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
using (FileStream fs = new FileStream(path, FileMode.Create))
{fs.Write(data, 0, data.Length);  // 写入二进制数据
}

Directory类提供了静态方法来创建、删除、移动和枚举目录(文件夹)等操作。

// 创建目录:
string directoryPath = "myDirectory";
if (!Directory.Exists(directoryPath))
{Directory.CreateDirectory(directoryPath);  // 创建目录
}// 获取目录下的文件列表:
string directoryPath = "myDirectory";
string[] files = Directory.GetFiles(directoryPath);  // 获取目录中的所有文件
foreach (var file in files)
{Console.WriteLine(file);
}// 删除目录:
string directoryPath = "myDirectory";
if (Directory.Exists(directoryPath))
{Directory.Delete(directoryPath, true);  // 删除目录及其所有内容
}

Path类提供了常见的路径操作方法,比如获取文件扩展名、文件名、合并路径等。

// 合并路径:
string directoryPath = @"C:\Users";
string fileName = "example.txt";
string fullPath = Path.Combine(directoryPath, fileName);  // 合并路径
Console.WriteLine(fullPath);// 获取文件扩展名:
string filePath = "example.txt";
string extension = Path.GetExtension(filePath);  // 获取文件扩展名
Console.WriteLine(extension);

FileInfo和DirectoryInfo类提供了文件和目录的详细信息,可以通过它们获取文件的大小、创建时间、修改时间等。

// 获取文件信息:
FileInfo fileInfo = new FileInfo("example.txt");
Console.WriteLine("File size: " + fileInfo.Length);
Console.WriteLine("Last modified: " + fileInfo.LastWriteTime);// 获取目录信息:
DirectoryInfo directoryInfo = new DirectoryInfo("myDirectory");
Console.WriteLine("Directory created: " + directoryInfo.CreationTime);

总结:C#提供了强大的文件输入输出功能可以方便地进行文件和目录的操作,通过System.IO命名空间中的类(如 File、StreamReader、StreamWriter、FileStream、Directory 等),可以进行各种文件和目录的创建、读取、写入、删除、复制等操作。在进行文件操作时确保正确处理异常并使用finally块来进行资源清理(如关闭文件流等),以提高程序的鲁棒性。

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

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

相关文章

普及组集训--图论最短路径设分层图

P4568 [JLOI2011] 飞行路线 - 洛谷 | 计算机科学教育新生态 可以设置分层图:(伪代码) E(u,v)w;无向图 add(u,v,w),add(v,u,w); for(j1~k){add(ujn,vjn,w);add(vjn,ujn,w);add(ujn-j,vjn-j,0);add(vjn-j,ujn-j,0); } add(ujn-j,vjn-j,0); add(vjn-j,uj…

常用传感器介绍合集

SW-520D倾斜传感器 HX711模块:高精度称重的核心利器 GY302光照传感器模块详解 MLX90614红外测温传感器介绍 MAX30102心率血氧传感器模块:精准健康监测的利器 RGB颜色传感器简介 DS18B20温度传感器模块 人体红外传感器简介 FC-28土壤湿度传感器 …

gitee常见命令

目录 1.本地分支重命名 2.更新远程仓库分支 3.为当前分支设置远程跟踪分支 4.撤销已经push远程的代码 5.idea->gitee的‘还原提交’ 需要和本地当前的代码解决冲突 解决冲突 本地工作区的差异代码显示 本地commit和push远程 6.idea->gitee的‘将当前分支重置到此…

C++设计模式(建造者、中介者、备忘录)

一、建造者模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 示例: //房子(产品类) class House { private:int rooms;int windows;string decoration; public:void setRooms(int r) {rooms …

简易图书管理系统

javawebjspservlet 实体类 package com.ghx.entity;/*** author :guo* date :Created in 2024/12/6 10:13* description:* modified By:* version:*/ public class Book {private int id;private String name;private double pri…

什么是甘特图?使用甘特图制定项目计划表的步骤

在项目管理中,项目计划是项目的核心要素,它详细记录了项目任务详情、责任人、时间规划以及所需资源。 这份计划不仅为项目推进提供指引,更是控制范围蔓延、争取更多支持的有力工具。 在项目管理中,项目计划是项目的核心要素&…

mock.js介绍

mock.js http://mockjs.com/ 1、mock的介绍 *** 生成随机数据,拦截 Ajax 请求。** 通过随机数据,模拟各种场景;不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据;支持生成随机的文本、数字…

16.[极客大挑战 2019]Upload1

进入靶场 是文件上传类题目 随便传个图片 制作个含木马的 算了&#xff0c;直接抓包只传文件改格式好了 第一次传的是<?php eval($_POST[attack]);?> 第二次传的是GIF89a? <script language"php">eval($_REQUEST[1])</script> "GIF89a&…

标书里的“废标雷区”:你踩过几个?

在投标领域&#xff0c;标书的质量不仅决定了中标的可能性&#xff0c;更是体现企业专业度的关键。但即便是经验丰富的投标人&#xff0c;也难免会在标书编制过程中踩中“废标雷区”。这些雷区可能隐藏在技术方案的细节中&#xff0c;也可能是投标文件格式的规范问题。以下&…

22、共用体

1、共用体 共用体 --- 用法和结构体类似 共用体&#xff1a;多个成员共用同一段内存空间。 1.1、共用体定义 union 共用体名 { 成员类型 成员名; 成员类型 成员名; .... }; 共用体的类型名&#xff1a;union 共用体名 例子&#xff1a; 定义一个共用体里面有两个成员&…

CVPR和其他2024顶会论文阅读(资源整理【1】)

CVPR 2024论文阅读(资源整理【1】) 一、3d 重建与建模论文1-Deformable 3D Gaussians for High-Fidelity Monocular Dynamic Scene Reconstruction论文2- 4D Gaussian Splatting for Real-Time Dynamic Scene Rendering论文3-GaussianDreamer: Fast Generation from Text to …

电脑投屏到电脑:Windows,macOS及Linux系统可以相互投屏!

本篇其实是电脑远程投屏到另一台电脑的操作介绍。本篇文章的方法可用于Windows&#xff0c;macOS及Linux系统的相互投屏。 为了避免介绍过程中出现“这台电脑”投屏到“那台电脑”的混乱表述&#xff0c;假定当前屏幕投出端是Windows系统电脑&#xff0c;屏幕接收端是Linux系统…

视频质量评价算法 DOVER 介绍

DOVER DOVER项目: DOVER是为ICCV2023会议论文“Exploring Video Quality Assessment on User Generated Contents from Aesthetic and Technical Perspectives”提供的官方代码、演示和权重的项目。官网:https://vqassessment.github.io/DOVER/ GitHub:https://github.com/V…

单片机上各种输出模式和寄存器讲解

零、目录 1&#xff0c;什么是寄存器 2&#xff0c;单片机各种输出模式及其应用 一、什么是寄存器 我们直接以STM32芯片的架构为例子 单片机芯片组成两部分&#xff1a;内核&#xff0c;外设&#xff08;相当于电脑的CPU和其他一件主板&#xff0c;键盘显示器等&#xff09;…

基于内核DWT延时

1.软件延时缺点 2.硬件延时&#xff0c;利用系统提供的嘀嗒定时器。1ms进一次。 3.内核架构。该监视只有Cortex3以上的才有。 4.DWT硬件延时方案 5.使用步骤

文件操作---文件IO与标准IO

目录 一、带参数的main函数 带参main函数的格式 带参main的示例 二、文件操作 1、文件结构 2、文件操作的方式 3、文件IO和标准IO区别 ①概念介绍 ②主要区别 三、文件IO 1、特性 2、操作流程 3、相关函数 open close write read lseek 4、综合示例…

./configure 安装ngnix的命令

./configure 是一个在 Unix 和类 Unix 系统中常用的 shell 脚本命令&#xff0c;主要用于配置软件源代码包&#xff0c;以便进行编译和安装。这个命令通常在从源代码编译软件之前执行&#xff0c;它会自动检测系统的配置并生成适合该系统的 Makefile。 以下是 ./configure 脚本…

沈阳工业大学《2024年827自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《沈阳工业大学827自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题

【DVWA】SQL Injection (Blind)

人的一生应当如何度过&#xff0c;我希望当我回首往事时&#xff0c;不因虚度年华而悔恨&#xff0c;也不因碌碌无为而羞愧&#xff0c;我可以对自己说&#xff1a;我不负此生。 1.SQL Injection (Blind)(Low) 相关代码分析 可以看到&#xff0c;Low级别的代码对参数id没有做…

【系统架构设计师论文】云上自动化运维及其应用

随着云计算技术的迅猛发展,企业对云资源的需求日益增长。为了应对这一挑战,云上自动化运维(CloudOps)应运而生,它结合了DevOps理念和技术,通过自动化工具和流程来提高云环境的管理效率和服务质量。本文将探讨云上自动化运维的主要衡量指标,并详细介绍一个实际项目中如何…