目录
一、什么是拓展方法?
二、拓展方法有啥用?怎么写拓展方法?
1. 核心用途
2. 编写步骤
实现步骤
关键点说明
关键规则
3. 注意事项
三、什么是运算符重载?
四、运算符重载有啥用?怎么写?
1. 核心用途
2. 编写步骤
3. 可重载的运算符
4. 注意事项
五、总结
对比表:拓展方法 vs 运算符重载
前言:当代码学会“七十二变”
有没有想过,让
string
类型突然学会统计单词数?或者让你的自定义类像int
一样支持加减乘除?C#的拓展方法就像“魔法外挂”,能让任何类型瞬间解锁新技能,而运算符重载则是“对象变身术”,让你的类摇身一变成为数学高手!
本文将揭秘这两个神器的使用秘籍,让你告别冗长代码,拥抱优雅语法——从此,你的代码不仅能“说话”,还能“算卦”!
拓展方法(Extension Methods)是C#中一种特殊的语法,允许为现有类型(包括密封类或系统类型)添加新方法,而无需修改原始代码或创建子类。
概念
为现有的 非静态变量 添加 新方法
作用
1.提高程序拓展性
2.不需要在对象中重新写方法
3.不需要继承来添加方法
4.为别人封装的类型写额外的方法
特点
1.一定是写在静态类中
2.一定是个静态函数
3.第一个参数为拓展目标
4.第一个参数用this修饰
this
关键字修饰,表示要扩展的类型。基本语法:访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,)
string
类型添加一个统计单词数的方法。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
var numbers = new List { 1, 2, 3 };
var sum = numbers.Where(n => n > 1).Sum(); // LINQ的Where和Sum均为拓展方法
Extensions
结尾(如 StringExtensions
)。this
修饰,表示目标类型。基本语法:访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,)
public static class MathExtensions {
public static double Square(this int num) => num * num;
}
// 使用
int num = 5;
Console.WriteLine(num.Square()); // 25
除了为系统内部的类型进行拓展方法,我们自己还可以为自己写的静态类进行拓展方法: 假设有一个 Product
类,表示商品信息:
ProductExtensions
的静态类。this Product product
修饰。Product
的公开属性。public class Product {
public string Name { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
}
我们希望为 Product
添加一个扩展方法,用于生成商品描述的格式化字符串,而无需修改 Product
类的原始代码。就可以如下书写:
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;
}
}
测试:
// 创建商品实例
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 ? "库存充足" : "库存不足");
// 输出:库存充足
关键点说明
静态类与静态方法:
- 所有扩展方法必须定义在
static class
中。- 方法本身必须是
static
的,且第一个参数用this
关键字标记目标类型。访问权限:
- 扩展方法只能访问目标类型的 **
public
成员**(如Product
的Name
、Price
)。- 无法访问
private
或protected
成员。命名空间依赖:
- 若扩展方法定义在命名空间
MyExtensions
中,使用时需通过using MyExtensions;
引入。
隐式传递实例:
product
)会自动成为静态方法的第一个参数。附加参数:
this
参数)外的其他参数,需在调用时显式传入。IsInStock(30)
中的 30
对应方法定义中的 requiredQuantity
。补充示例:为系统自带类int拓展的方法:
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
运算符重载(Operator Overloading)允许为自定义类型重新定义运算符的行为(如 +
, ==
, >
等)。
概念
让自定义的类和结构体
能够运用运算符使用关键字
operator特点
1.一定是一个公共的静态方法
2.返回值写在operator前
3.逻辑处理自定义作用
让自定义类和结构体对象可以进行运算
注意
1.条件运算符需要成对出现
2.一个符号可以多次重载
3.不能使用ref out
operator
关键字定义。public static
方法。Vector
类重载 +
运算符。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
a + b
替代 a.Add(b)
。语法:public static 返回类型 operator 运算符(参数列表)
如下是一个用来计算温度的 “ + ”:
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);
}
}
运算符类型 | 示例 |
---|---|
算术运算符 | + , - , * , / , % |
比较运算符 | == , != , > , < , >= , <= |
转换运算符 | implicit 或 explicit |
==
必须同时重载 !=
)。=
、+=
)。+
执行减法操作)。特性 | 拓展方法 | 运算符重载 |
---|---|---|
核心目的 | 扩展现有类型的功能 | 自定义类型支持运算符操作 |
语法要求 | 静态类 + this 参数 |
public static operator |
适用场景 | 工具方法、链式调用、LINQ | 数学运算、集合操作、语义化操作 |
限制 | 无法访问私有成员 | 需成对重载、不能重载所有运算符 |
一句话记忆:
掌握这两个特性,让你的C#代码像自然语言一样直观!