C# 中 12 个优化代码与提升效率的实用技巧

124 阅读4分钟

前言

随着 C# 语言版本更新,微软不断引入新的语法特性和改进,以帮助我们编写更简洁、高效且易于维护的代码。掌握这些特性不仅能提高编程效率,还能提升代码的质量和可读性。

本文将介绍 12 个非常有用的 C# 语法特性,并通过示例代码详细说明它们的应用场景和优势。

正文

1、空合并赋值(??=)

当变量为 null 时,使用空合并赋值运算符可以对其进行赋值,从而简化检查和赋值操作。

示例代码

string name = null;
name ??= "DotNET技术匠";
Console.WriteLine(name); 
// 输出:DotNET技术匠

说明:在上述代码中,如果 namenull,则会被赋值为 "DotNET技术匠"。

这种写法避免了繁琐的 if 判断和赋值语句,使代码更加简洁。

2、空条件运算符(?.)

空条件运算符允许我们在访问对象成员之前先检查对象是否为 null,从而避免空引用异常的发生。

示例代码

Person person = null;
string address = person?.Address;
Console.WriteLine(address); 
// 输出:null

说明:在访问 personAddress 属性之前,会先检查 person 是否为 null

如果是 null,则 address 也会被赋值为 null,而不会引发空引用异常。

3、字符串插值($)

字符串插值功能允许我们将表达式直接嵌入到字符串中,使字符串的构造更加简洁和直观。

示例代码

string name = "小码编匠";
int age = 18;
string info = $"Name: {name}, Age: {age}";
Console.WriteLine(info);
// 输出:Name: 小码编匠, Age: 18

说明:通过在字符串前加 $ 符号,可以直接在字符串中插入变量 nameage 的值,无需使用 String.Format 方法,使代码更加易读。

4、模式匹配(is 和 switch)

模式匹配功能使我们能够一步完成类型检查和转换,或者根据类型执行特定的操作。

示例代码

object obj = "Hello, World!";
if (obj is string str)
{
    Console.WriteLine(str.ToUpper()); // 输出:HELLO, WORLD!
}

switch (obj)
{
    case string s:
        Console.WriteLine(s.ToLower());
        break;
    case int i:
        Console.WriteLine(i + 1);
        break;
    default:
        Console.WriteLine("Unknown type");
        break;
}

说明:使用 is 关键字可以同时进行类型检查和变量声明,而 switch 表达式可以根据对象的类型执行不同的操作,使代码更加灵活和简洁。

5、用于可释放对象的 using 语句

using 语句确保在使用完实现了 IDisposable 接口的对象后,自动对其进行释放,从而避免资源泄露。

示例代码

using (FileStream fs = new FileStream("example.txt", FileMode.Create))
{
    // 对文件流进行操作
}
// 文件流 fs 在此处已被自动关闭和释放

说明using 语句确保在代码块执行完毕后,即使发生异常,也会调用对象的 Dispose 方法,释放资源,使代码更加安全和可靠。

6、带有异常筛选的 try-catch

带有异常筛选的 try-catch 结构允许我们根据条件捕获特定类型的异常,从而实现更精细的异常处理。

示例代码

try
{
    // 可能引发异常的代码
}
catch (Exception ex) when (ex is FileNotFoundException)
{
    Console.WriteLine("File not found");
}

说明:通过 when 子句可以对捕获的异常进行筛选,只捕获满足特定条件的异常,使异常处理更加有针对性。

7、nameof 运算符

nameof 运算符可以以字符串形式提供变量、属性或方法的名称,这在日志记录和错误处理方面非常有用。

示例代码

void LogPropertyChange(string propertyName, object oldValue, object newValue)
{
    Console.WriteLine($"Property {propertyName} changed from {oldValue} to {newValue}");
}

int age = 30;
age = 31;
LogPropertyChange(nameof(age), 30, 31); 
// 输出:Property age changed from 30 to 31

说明nameof 运算符可以获取变量 age 的名称作为字符串,避免了硬编码字符串带来的错误和维护困难。

8、局部函数

局部函数允许我们在方法内部定义小型辅助函数,避免在类中出现不必要的额外方法,从而提高代码的封装性和可维护性。

示例代码

void ProcessData()
{
    void LogData(string data)
    {
        Console.WriteLine($"Data: {data}");
    }

    LogData("Sample data");
}

说明:局部函数 LogData 只在 ProcessData 方法内部可见和可用,有助于保持代码的整洁和组织结构。

9、元组解构

元组解构功能简化了从元组中解包多个返回值的操作,使代码更加简洁和直观。

示例代码

(int, string) GetUserInfo()
{
    return (18, "小码编匠");
}

var (age, name) = GetUserInfo();
Console.WriteLine($"Name: {name}, Age: {age}"); 
// 输出:Name: 小码编匠, Age: 18

说明:通过元组解构,可以方便地将返回的元组值赋给多个变量,避免了繁琐的解包操作。

10、表达式主体成员

表达式主体成员允许我们使用简洁的语法定义方法和属性,使代码更加紧凑和易读。

示例代码

int GetSum(int a, int b) => a + b;

int Sum { get; set; } = 0;

说明:表达式主体成员允许使用 => 语法简化方法和属性的定义,减少了代码的冗余和复杂性。

11、只读结构体

只读结构体是一种不可变的数据结构,它定义了只读的字段和属性,从而减少了内存分配并提高了性能。

示例代码

readonly struct Point
{
    public readonly int X;
    public readonly int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Point p = new Point(1, 2);
// p.X = 3; 
// 错误:不能修改只读字段

说明:只读结构体的所有字段和属性都是只读的,不能被修改,这有助于确保数据的完整性和一致性。

12. switch 表达式

switch 表达式为 switch 语句提供了一种更简洁且更具函数式风格的写法,使代码更加清晰和高效。

示例代码

int number = 2;
string result = number switch
{
    1 => "One",
    2 => "Two",
    3 => "Three",
    _ => "Unknown"
};

Console.WriteLine(result); 
// 输出:Two

说明switch 表达式可以直接返回匹配的值,无需使用 break 语句,使代码更加简洁和易于理解。

总结

上述 12 个 C# 语法特性不仅能够简化日常编码工作,还提高了代码的可读性和健壮性。无论是简化空值处理、增强类型安全性,还是优化资源管理,每个特性都在让我们的开发过程更加流畅高效。在实际开发中,合理运用这些技巧,可以减少错误的发生,提升代码质量。希望本文的介绍能够帮助大家更好地理解和应用这些 C# 语法技巧,从而在编程道路上更进一步。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!