C#核心学习(七)面向对象--封装(6)C#中的拓展方法与运算符重载: 让代码更“聪明”的魔法

目录

一、什么是拓展方法?

二、拓展方法有啥用?怎么写拓展方法?

[1. ​核心用途](#1. 核心用途)

[2. ​编写步骤](#2. 编写步骤)

实现步骤

关键点说明

关键规则

[3. ​注意事项](#3. 注意事项)

三、什么是运算符重载?

四、运算符重载有啥用?怎么写?

[1. ​核心用途](#1. 核心用途)

[2. ​编写步骤](#2. 编写步骤)

[3. ​可重载的运算符](#3. 可重载的运算符)

[4. ​注意事项](#4. 注意事项)

五、总结

[​对比表:拓展方法 vs 运算符重载](#对比表:拓展方法 vs 运算符重载)


前言:当代码学会"七十二变"​

有没有想过,让 string 类型突然学会统计单词数?或者让你的自定义类像 int 一样支持加减乘除?

C#的拓展方法就像"魔法外挂",能让任何类型瞬间解锁新技能,而运算符重载则是"对象变身术",让你的类摇身一变成为数学高手!

本文将揭秘这两个神器的使用秘籍,让你告别冗长代码,拥抱优雅语法------从此,你的代码不仅能"说话",还能"算卦"!

一、什么是拓展方法?

拓展方法(Extension Methods)​ 是C#中一种特殊的语法,允许为现有类型(包括密封类或系统类型)添加新方法,而无需修改原始代码或创建子类。

概念
为现有的 非静态变量 添加 新方法
作用
1.提高程序拓展性
2.不需要在对象中重新写方法
3.不需要继承来添加方法
4.为别人封装的类型写额外的方法
特点
1.一定是写在静态类中
2.一定是个静态函数
3.第一个参数为拓展目标
4.第一个参数用this修饰

  • 核心特点
    • 定义在静态类中,方法为静态方法。
    • 第一个参数用 this 关键字修饰,表示要扩展的类型。
    • 扩展方法的本质是一个静态方法 ,但在调用时,编译器会自动将实例对象(即调用者)​作为第一个参数传递进去。这种语法糖让扩展方法看起来像是实例方法,但实际上背后是静态方法的调用逻辑。

基本语法:访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,)

  • 示例 :为 string 类型添加一个统计单词数的方法。
cs 复制代码
public static class StringExtensions {
    public static int WordCount(this string str) {
        return str.Split(new[] {' ', '.', '?'}, StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

// 使用
string text = "Hello, how are you?";
Console.WriteLine(text.WordCount()); // 输出 4

二、拓展方法有啥用?怎么写拓展方法?

1. ​核心用途

  • 扩展现有类型功能:尤其适用于无法修改源码的类(如系统类型或第三方库)。
  • 链式调用:让代码更流畅(如LINQ基于拓展方法实现)。
cs 复制代码
var numbers = new List<int> { 1, 2, 3 };
var sum = numbers.Where(n => n > 1).Sum(); // LINQ的Where和Sum均为拓展方法

2. ​编写步骤

  1. 创建静态类 :类名建议以 Extensions 结尾(如 StringExtensions)。
  2. 定义静态方法 :第一个参数用 this 修饰,表示目标类型。

基本语法:访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,)

cs 复制代码
public static class MathExtensions {
    public static double Square(this int num) => num * num;
}
// 使用
int num = 5;
Console.WriteLine(num.Square()); // 25

除了为系统内部的类型进行拓展方法,我们自己还可以为自己写的静态类进行拓展方法: 假设有一个 Product 类,表示商品信息:

实现步骤
  1. 定义静态类 :创建名为 ProductExtensions 的静态类。
  2. 编写扩展方法 :添加一个静态方法,第一个参数用 this Product product 修饰。
  3. 实现逻辑 :在方法内部访问 Product 的公开属性。
cs 复制代码
public class Product {
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
}

我们希望为 Product 添加一个扩展方法,用于生成商品描述的格式化字符串,而无需修改 Product 类的原始代码。就可以如下书写:

cs 复制代码
public static class ProductExtensions {
    // 扩展方法:生成商品描述
    public static string GetDescription(this Product product) {
        return $"{product.Name} - 价格:¥{product.Price},库存:{product.Stock}件";
    }

    // 扩展方法:检查库存是否充足
    public static bool IsInStock(this Product product, int requiredQuantity) {
        return product.Stock >= requiredQuantity;
    }
}

测试:

cs 复制代码
// 创建商品实例
var product = new Product {
    Name = "无线蓝牙耳机",
    Price = 299.99m,
    Stock = 50
};

// 调用扩展方法
string description = product.GetDescription();
bool isAvailable = product.IsInStock(30);

Console.WriteLine(description); 
// 输出:无线蓝牙耳机 - 价格:¥299.99,库存:50件
Console.WriteLine(isAvailable ? "库存充足" : "库存不足"); 
// 输出:库存充足

关键点说明

  1. 静态类与静态方法:

    • 所有扩展方法必须定义在 static class 中。
    • 方法本身必须是 static 的,且第一个参数用 this 关键字标记目标类型。
  2. 访问权限:

    • 扩展方法只能访问目标类型的 **public 成员**(如 ProductNamePrice)。
    • 无法访问 privateprotected 成员。
  3. 命名空间依赖:

    • 若扩展方法定义在命名空间 MyExtensions 中,使用时需通过 using MyExtensions; 引入。

关键规则

  1. 隐式传递实例

    • 调用扩展方法时,实例对象(如 product)会自动成为静态方法的第一个参数。
    • 你无需(也不能)手动传递该参数。
  2. 附加参数

    • 扩展方法定义中除第一个参数(this参数)外的其他参数,需在调用时显式传入。
    • 例如 IsInStock(30) 中的 30 对应方法定义中的 requiredQuantity

补充示例:为系统自带类int拓展的方法:

cs 复制代码
public static class IntExtensions {
    // 判断数字是否为偶数
    public static bool IsEven(this int number) {
        return number % 2 == 0;
    }

    // 计算数字的平方
    public static int Square(this int number) {
        return number * number;
    }
}

// 使用
int num = 5;
Console.WriteLine(num.IsEven()); // 输出 False
Console.WriteLine(num.Square()); // 输出 25

3. ​注意事项

  • 拓展方法优先级低于类的实例方法。
  • 无法访问类型的私有成员。
  • 需通过命名空间引入拓展方法所在的类。

三、什么是运算符重载?

运算符重载(Operator Overloading)​ 允许为自定义类型重新定义运算符的行为 ​(如 +, ==, > 等)。

概念
让自定义的类和结构体
能够运用运算符

使用关键字
operator

特点
1.一定是一个公共的静态方法
2.返回值写在operator前
3.逻辑处理自定义

作用
让自定义类和结构体对象可以进行运算
注意
1.条件运算符需要成对出现
2.一个符号可以多次重载
3.不能使用ref out

  • 核心规则
    • 使用 operator 关键字定义。
    • 必须是 public static 方法。
  • 示例 :为自定义的 Vector 类重载 + 运算符。
  • 语法:public static 返回类型 operator 运算符(参数列表)
cs 复制代码
public class Vector {
    public int X { get; }
    public int Y { get; }
    
    public Vector(int x, int y) { X = x; Y = y; }
    
    public static Vector operator +(Vector a, Vector b) {
        return new Vector(a.X + b.X, a.Y + b.Y);
    }
}

// 使用
Vector v1 = new Vector(1, 2);
Vector v2 = new Vector(3, 4);
Vector sum = v1 + v2; // sum.X=4, sum.Y=6

四、运算符重载有啥用?怎么写?

1. ​核心用途

  • 自然语义:让自定义类型支持直观的运算符操作(如复数相加、矩阵乘法)。
  • 提高可读性 :用 a + b 替代 a.Add(b)

2. ​编写步骤

  1. 定义运算符方法:指定运算符和操作数类型。
  2. 实现运算逻辑:返回计算结果

语法:public static 返回类型 operator 运算符(参数列表)

如下是一个用来计算温度的 " + ":

cs 复制代码
public class Temperature {
    public double Celsius { get; }
    public Temperature(double celsius) { Celsius = celsius; }
    
    public static Temperature operator +(Temperature t1, Temperature t2) {
        return new Temperature(t1.Celsius + t2.Celsius);
    }
}

3. ​可重载的运算符

运算符类型 示例
算术运算符 +, -, *, /, %
比较运算符 ==, !=, >, <, >=, <=
转换运算符 implicitexplicit

4. ​注意事项

  • 必须成对重载(如重载 == 必须同时重载 !=)。
  • 不能重载赋值运算符(如 =+=)。
  • 避免过度使用导致逻辑混乱(如让 + 执行减法操作)。

五、总结

对比表:拓展方法 vs 运算符重载

特性 拓展方法 运算符重载
核心目的 扩展现有类型的功能 自定义类型支持运算符操作
语法要求 静态类 + this 参数 public static operator
适用场景 工具方法、链式调用、LINQ 数学运算、集合操作、语义化操作
限制 无法访问私有成员 需成对重载、不能重载所有运算符

一句话记忆

  • 拓展方法:"别人家的孩子,我来教他新技能。"
  • 运算符重载:"我的对象,加减乘除我说了算!"

掌握这两个特性,让你的C#代码像自然语言一样直观!

相关推荐
“抚琴”的人16 小时前
【机械视觉】C#+VisionPro联合编程———【六、visionPro连接工业相机设备】
c#·工业相机·visionpro·机械视觉
云上艺旅16 小时前
K8S学习之基础七十四:部署在线书店bookinfo
学习·云原生·容器·kubernetes
你觉得20517 小时前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义下载方法
大数据·人工智能·python·gpt·学习·机器学习·aigc
A旧城以西18 小时前
数据结构(JAVA)单向,双向链表
java·开发语言·数据结构·学习·链表·intellij-idea·idea
无所谓จุ๊บ18 小时前
VTK知识学习(50)- 交互与Widget(一)
学习·vtk
吴梓穆18 小时前
UE5学习笔记 FPS游戏制作38 继承标准UI
笔记·学习·ue5
CodeCraft Studio19 小时前
Excel处理控件Spire.XLS系列教程:C# 合并、或取消合并 Excel 单元格
前端·c#·excel
Three~stone19 小时前
MySQL学习集--DDL
数据库·sql·学习
齐尹秦19 小时前
HTML 音频(Audio)学习笔记
学习