msdn是这样给扩展方法定义的:
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。
可能你在第一次看到的时候有点晕,下面就通过一个小的demo来讲解一下。
新建一个项目命名为:ExtensionMethods,项目结构如下图所示:
首先讲解一下Employee,Employees,Salary类
Employee:Employee model有Name,Gender,Age,Salary属性,重载了object的ToSring()方法,用于返回Employee信息。
public sealed class Employee
{
public string Name { get; set; }
public Gender Gender { get; set; }
public int Age { get; set; }
public Salary Salary { get; set; }
public Employee(string name, Gender gender, int age, Salary salary)
{
this.Name = name;
this.Gender = gender;
this.Age = age;
this.Salary = salary;
}
public override string ToString()
{
return string.Format("Name:{0} Gender:{1} Age:{2} Salary:{3}", Name, Gender.ToString(), Age.ToString(), Salary.GetSalary().ToString());
}
}
public enum Gender
{
MALE,
FORMALE
}
Employees:一个Employee 的列表。
public class Employees
{
private IList<Employee> empleoyees = null;
public Employees()
{
empleoyees = new List<Employee>();
//initialize the sample data for test.
initializeSampleData();
}
private void initializeSampleData()
{
if (empleoyees == null)
empleoyees = new List<Employee>();
var lastGender = Gender.MALE;
for (int i = 0; i < 10; i++)
{
//add test data.
lastGender = (lastGender == Gender.MALE ? Gender.FORMALE : Gender.MALE);
empleoyees.Add(new Employee("employee:" + i.ToString(),
lastGender,
(i + 1) * 1000,
new Salary(new Random().Next(10000, 20000))));
}
}
public IList<Employee> GetEmployees()
{
return empleoyees;
}
}
Salary:用于计算employee的salry.
public class Salary
{
public float BaseSalary { get; set; }
public Salary(float _baseSalary)
{
this.BaseSalary = _baseSalary;
}
public float GetSalary()
{
return BaseSalary;
}
}
如果我想得到一个Emploeyee的列表,只要调用Employees类的GetEmployees方法就可以了,像这样:
IList<Employee> employees = new Employees().GetEmployees();
那如果我想把列表中的内容输出出来,该怎么办呢?
你可以这样:
IList<Employee> employees = new Employees().GetEmployees();
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i].ToString());
}
如果你在别的地方也需要把内容输出该怎么办呢?复制还是把方法提出来?这时候还有一个更好的方法,那就是使用扩展方法,就是demo中的ExtensionEmployee,代码如下:
public static class ExtensionEmployee
{
public static void DisplayEmployeesInfo(this List<Employee> employees)
{
if (employees == null)
return;
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i].ToString());
}
}
}
使用方法:
List<Employee> employees = (List<Employee>)new Employees().GetEmployees();
employees.DisplayEmployeesInfo();
签名方式:
扩展方法的语法点是类和方法的签名必须是pulic和static,扩展方法的第一个参数前加this修饰,用来指示要操作的数据对象,在本demo中就是employees变量,这样就可以像调用List<T>本身的方法一样使用它了,另外扩展方法还支持扩展接口,例如我把demo中扩展方法的签名改成:
public static void DisplayEmployeesInfo(this IList<Employee> employees)
这样的话,List<Employee>和IList<Employee>都可以直接使用这个扩展方法了。
扩展方法的工作方式:
在编译时,它首先会查找IList<T>类型,查看该类型是否定义了DisplayEmployeesInfo方法,如果找到了,会进行调用,如果没有找到,会在全局搜索所有的静态类,查找该静态类下面是否有一个名为DisplayEmployeesInfo的方法,并且该方法的第一个参数用this标记,且参数类型与IList<Employee>兼容,如果找到则进行调用。
你也许会问,如果自己定义的扩展方法名称在该类型中已经存在,并且方法签名也一样会怎么样呢?这时会优先使用类型原生的方法。
demo下载地址:http://yunpan.cn/QDv5CT2DxnDyj
欢迎指正!
谢谢