扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。仅当你使用 using 指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。
在代码中,可以使用实例方法语法调用该扩展方法。但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。因此,并未真正违反封装原则。实际上,扩展方法无法访问它们所扩展的类型中的私有变量。通常,我们更多时候是调用扩展方法而不是实现你自己的扩展方法。由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。
可以使用扩展方法来扩展类或接口,但不能重写扩展方法。与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。换句话说,如果某个类型具有一个名为 Process(int i) 的方法,而你有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法。
using System; using static System.Console; namespace 扩展方法 { class Program { static void Main(string[] args) { //字段扩展方法 string str = null; str.SayHello(); string newStr = "你好"; newStr.SayHello(); //类扩展方法 Enemy enemy =new Enemy(100,200); WriteLine(enemy.GetAvg()); //泛型扩展方法 Monster<int> monster=new Monster<int>(500); WriteLine(monster.GetSum()); ReadKey(); } } //明扩展方法的类必须是static类,并且方法也要是static类型 //扩展方法必须包含this关键字作为它的第一个参数类型,并且后面跟着它所扩展的类的名称 // 必须是一个静态类 public static class Extension { //必须为public static 类型,且参数使用this关键字 public static void SayHello(this string str) { if (str==null) { WriteLine("Hello"); } else { WriteLine("{0}",str); } } } //为类添加扩展方法 class Enemy { private int hp, age; public Enemy(int hp, int age) { this.hp = hp; this.age = age; } public int GetSum() { return hp + age; } } static class ExtendEnemy { public static int GetAvg(this Enemy enemy) { return enemy.GetSum() / 2; } } //为泛型添加扩展方法 public class Monster<T> { private T data; public Monster(T data) { this.data = data; } public T GetData() { return data; } } public static class ExtendMonster { public static T GetSum<T>(this Monster<T> monster) { return monster.GetData(); } } }