一、基础
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,调用扩展方 法与调用在类型中实际定义的方法之间没有明显的差异。扩展方法是可以通过使用实例方法语法调用的静态方法。效果上,使得附加的方法扩展已存在类型和构造类 型成为可能。他可以对现有类功能进行扩充,从而使该类型的实例具有更多的方法。扩展方法有助于把今天动态语言中流行的对快速录入支持的灵活性,与强类型语 言之性能和编译时验证融合起来。这里先举一个msdn中的例子:
下面的示例演示为 System.String 类定义的一个扩展方法。假设我要分析一个字符串,希望得到字符串中单词的个数,一般情况下我们可能使用一个统计的函数来解决这个问题
但这样用起来感觉上可能会很别扭,这个WordCount方法如果就是 字符串类中的一个方法多好,像所有字符串的实例方法一样用。这里我们引出扩展方法来解决这个问题。
注意,上面的静态方法在第一个类型是string的参数变量前有个 “this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为“string”的对象中去。
使用 using 指令将 WordCount 扩展方法放入范围中:
using ExtensionMethods;
int i = s.WordCount();
二、应用场景
1、扩展类库中已经存在的类
比方说我们是无法改变系统已经存在的类的,就像上例中我们无法在string类中添加WordCount方法,但我又希望在使用时直接使用
这篇文章c#扩展方法奇思妙用中也有很多例子,大家可以参考一下
2、多个类实现接口时有些方法实现方式相同,所以不希望每个实现类中重新实现一遍
假如系统中用户接口需要两个类实现,希望IUser接口声明的实体都有检测Email的方法IsUniqueEmail,而实际上这个方法在所有实 现类中的实现逻辑都是一样的,而我们如果把这个方法添加到IUser中,那么两个类就要都实现一遍IsUniqueEmail的逻辑。中间加一层继承关系 也可以解决问题,这种方式会增加维护成本,这时我们可以使用扩展方法
如下图:
代码模拟如下:
interface IUser { string Email { get; set; } string Name { get; set; } } class UserLinqToOracle : IUser { #region IUser 成员 private string email; public string Email { get { return email; } set { email=value; } } private string name; public string Name { get { return name; } set { name = value; } } #endregion } class UserLinqToSql : IUser { #region IUser 成员 private string email; public string Email { get { return email; } set { email=value; } } private string name; public string Name { get { return name; } set { name = value; } } #endregion }
static class UserExtension { public static bool IsUniqueEmail(this IUser forUser, string email) { return CheckEmail(email); } private static bool CheckEmail(string email) { return true; } }
static void Main(string[] args) { IUser user = new UserLinqToOracle(); Console.WriteLine(user.IsUniqueEmail("")); }
三、扩展方法要点
1、扩展方法的本质为将实例方法调用在编译 期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能。
2、通常,您更多时候是调用扩展方法而不是实现您自己的扩展方 法。由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。若要为特定类型启用扩展方法,只需为在其中定义这些方法 的命名空间添加 using 指令。
3、扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后 为较远的namespace下的静态类的静态方法。(与接口或类方法具有相同名称和签名的扩展方法永远不会被调用 )
class Program { static void Main(string[] args) { User user = new User() { FirstName = "l", LastName = "fm" }; Console.WriteLine(user.FullName()); } } public class User { public string FirstName { get; set; } public string LastName { get; set; } public string FullName() { return "来源于实例方法:" + FirstName + LastName; } } public static class MyExtensions { public static string FullName(this User user) { return "来源于扩展方法:"+user.FirstName+user.LastName; } }
结果为“来源于实例方法:lfm”
namespace ConsoleApplication7
{
using MyNamespace;
class Program
{
static void Main(string[] args)
{
User user = new User() { FirstName = "l", LastName = "fm" };
Console.WriteLine(user.FullName());
}}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public static class MyExtensions
{
public static string FullName(this User user)
{
return "来源于较近的扩展方法:"+user.FirstName+user.LastName;
}
}
}
namespace MyNamespace
{
using ConsoleApplication7;
public static class MyExtensions
{
public static string FullName( 赞(0) 打赏相关推荐
- C#/.NET/.NET Core优秀项目和框架2024年7月简报 - 追逐时光者 - 博客园
- C#/.NET/.NET Core优秀项目和框架2024年6月简报 - 追逐时光者 - 博客园
- 使用c#强大的表达式树实现对象的深克隆 - a1010 - 博客园
- 关于使用NewtonSoft.Json库反序列化遭遇Unexpected character的解决记录-CSDN博客
- C# 怎么用OpenCVSharp4实现图片表格识别
- 打造自己的视频会议系统 GGMeeting(附送源码,PC+手机,支持Linux、国产OS、银河麒麟、统信UOS) - C#开源即时通讯GGTalk - 博客园
- 源码下载中心 - C#开源即时通讯GGTalk - 博客园
- GGTalk 开源即时通讯系统源码剖析之:数据库设计 - C#开源即时通讯GGTalk - 博客园