概念
扩展方法(Extension Methods)是C#3.0时引入的新特性,是一种特殊类型的静态方法。对于一个C#类型,如类、引用类型、值类型、接口等,扩展方法可以在不改变该类型源码的前提下,为它的实例提供新的成员。因此,若要为一个框架或第三方库的某个类型增加辅助功能,通过扩展方法就可以轻而易举的实现。
定义
- 声明扩展方法的类必须为static类;
- 扩展方法本身也必须声明为static;
- 扩展方法必须包含关键字this作为第一个参数类型,并在后面跟着它所扩展的类型的名称。
例如:针对int类型,计算int对象的平方的扩展方法如下所示:
/// <summary>
/// 自定义的扩展方法:必须是在静态类中
/// </summary>
public static class CustomExtendMethod
{
/// <summary>
/// 针对int类型的扩展的方法
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static int Square(this int num)
{
return num * num;
}
}
带参数的扩展方法
带参数的扩展方法定义格式: static 方法名 (this 目标类型 目标类型参数,参数类型1,参数名2,… )
/// <summary>
/// 针对对象扩展有参数方法
/// </summary>
/// <param name="course">要扩展的类型</param>
/// <param name="period">第一个参数</param>
/// <returns></returns>
public static string ShowCourse(this Course course, int period)
{
return string.Format($"{course.CourseName }:直播次数:{period} ");
}
总结
- 扩展方法必须定义在静态类中,扩展方法本身也是静态方法,扩展方法也可以重载。
- 如果扩展方法和对应的类位于不同的命名空间,使用时应引入扩展方法所在静态类的命名空间。
- 当类本身的方法与扩展方法重名时,类本身的方法被优先调用。(建议通过命名空间的方式来限制扩展方法的使用)
- 扩展方法不要过多使用。尤其是系统定义的类,不要随意增加扩展方法。
完整实例
// 先定义动物对象
public class Animal
{
public string Name { get; set; }
public string Species { get; set; }
public int Age { get; set; }
public double Weight { get; set; }
}
/// <summary>
/// 自定义的扩展方法:必须是在静态类中
/// </summary>
public static class CustomExtendMethod
{
/// <summary>
/// 针对int类型的扩展的无参数的方法
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static int Square(this int num)
{
return num * num;
}
/// <summary>
/// 重新定义系统的扩展方法
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string ToString(this int num)
{
return $"这是对数字{num}重新定义的ToString方法:";
}
/// <summary>
/// 针对对象扩展无参数方法
/// </summary>
/// <param name="dog"></param>
/// <returns></returns>
public static string Introduce(this Animal dog)
{
return $"大家好!我是{dog.Name},很高兴认识大家";
}
/// <summary>
/// 针对对象扩展有参数方法
/// </summary>
/// <param name="dog">要扩展的类型</param>
/// <param name="num">第一个参数</param>
/// <returns></returns>
public static string AddWeight(this Animal dog, int num)
{
return $"我原先的体重是{dog.Weight},又增加了{num}";
}
/// <summary>
/// 自定义一个扩展方法实现查询
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <param name="source"></param>
/// <param name="predicate">有一个输入参数,一个输出参数</param>
/// <returns></returns>
public static IEnumerable<TSource> MyCustomWhere<TSource>
(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
//创建一个集合
List<TSource> list = new List<TSource>();
//遍历查找
foreach (var item in source)
{
if (predicate(item))
{
list.Add(item);
}
}
return list;
}
}
// 测试方法
static void Main(string[] args)
{
Console.WriteLine("\r\n****************扩展方法的使用*******************");
int num = 10;
int result = num.Square();
Console.WriteLine(result);
Console.WriteLine(num.ToString());
var dog = new Animal()
{
Name = "小花",
Age = 5,
Species = "哈士奇",
Weight = 20
};
Console.WriteLine(dog.Introduce());
Console.WriteLine(dog.AddWeight(10));
//扩展方法的更多应用
Console.WriteLine("\r\n*******************扩展方法的更多应用*****************");
List<Animal> dogList = new List<Animal>()
{
new Animal { Name="长江1号", Age=5,Species="哈士奇", Weight=25},
new Animal { Name="长江2号", Age=6,Species="哈士奇", Weight=35},
new Animal { Name="长江3号", Age=7,Species="哈士奇", Weight=45},
new Animal { Name="长江4号", Age=8,Species="哈士奇", Weight=20},
};
Console.WriteLine("\r\n*******************使用自带的where扩展查询方法*****************");
var list1 = dogList.Where(c => c.Age > 6);
foreach (var item in list1)
{
Console.WriteLine($"{item.Name}\t{item.Age}\t{item.Species}\t{item.Weight}");
}
Console.WriteLine("\r\n*******************自定义扩展查询方法*****************");
var list2 = dogList.MyCustomWhere(c => c.Age > 6);
foreach (var item in list2)
{
Console.WriteLine($"{item.Name}\t{item.Age}\t{item.Species}");
}
Console.Read();
}