面试的时候面试官问了我如果一个类库我都分装号了,但是我突然要往类里边加一个方法,但是我不知道有扩展方法这个么东西,所以就说了一下分部类,但是上午实现了一下扩展方法,感觉还是挺不错的,在这里给大家分享一下。
面试官问的问题确实是需要我们考虑的,我们再程序设计的时候,不可能说是所有的东西都是一下就能设计好,难免会遗漏一些方法,可是如果真的是需要在一个类中添加方法呢,但是我们的类库已经编译成一个DLL文件,这个时候我们就需要用扩展方法了。
官方说法:扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。
简单理解:就是一个静态类里边放一个静态方法,然后在方法的参数中制定我们要把这个方法定义成谁的扩展方法。下次用的时候就实例化我们以前的类,调用我们写的扩展方法。
首先给大家看一个简单的例子。
扩展方法
namespace Extensions
{
public static class Extension
{
/// <summary>
/// 为String类添加要给扩展方法
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static int WordCout(this String str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length ;
}
}
}
客户端调用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExtensionMethodsDemo1;
using DefineMyInterface;
using Extensions1;
namespace DefineIMyInterface
{
class Program
{
static void Main(string[] args)
{
string s = "meng hai bin,ddd";
int i = s.WordCout();
Console.WriteLine("字符个数为" + i);
}
}
}
上边就是一个为String类添加扩展方法的例子。我们可以使用扩展方法来扩展类或接口,但不能重写扩展方法。 与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。 编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。 换句话说,如果某个类型具有一个名为 Process(int i) 的方法,而你有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。
当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。 如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法。 下面的示例演示编译器如何确定要绑定到哪个扩展方法或实例方法。
下边为大家实现要给小例子来证明一下上边说的大道理:
扩展方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DefineMyInterface;
namespace Extensions1
{
public static class Extension
{
public static void MethodA(this IMyInterface myInterface, int i)
{
Console.WriteLine("Extension.MethodA(this IMyInterface myINterface,int i)");
}
public static void MehtodA(this IMyInterface myInterface, string s)
{
Console.WriteLine("Extension.MethodB(this IMyinterface myInterface,string s)");
}
public static void MethodB(this IMyInterface myInterface)
{
Console.WriteLine("Extension.Method(this IMyInterface myInterface)");
}
}
}
接口:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DefineMyInterface
{
public interface IMyInterface
{
void MethodB();
}
}
实现类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DefineMyInterface;
namespace ExtensionMethodsDemo1
{
public class A:IMyInterface
{
public void MethodB()
{
Console.WriteLine("A.MethodB()");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DefineMyInterface;
namespace ExtensionMethodsDemo1
{
public class B : IMyInterface
{
public void MethodB()
{
Console.WriteLine("B.MethodB()");
}
public void MethodA(int i)
{
Console.WriteLine("B.MethodA(int i)");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DefineMyInterface;
namespace ExtensionMethodsDemo1
{
public class C : IMyInterface
{
public void MethodB()
{
Console.WriteLine("C.MehtodB");
}
public void MethodA(object obj)
{
Console.WriteLine("C.mehtodA(object obj)");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExtensionMethodsDemo1;
using DefineMyInterface;
using Extensions1;
namespace DefineIMyInterface
{
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
a.MethodB();
a.MethodA(1);
b.MethodA(1);
b.MethodB();
b.MehtodA("hello");
c.MethodA(1);
c.MethodA("hello");
c.MethodB();
}
}
} 效果如下:
也就是说只有类A的MethodA,B类的MethodB实现了,因为他们在原来的类里边没有实现,所以才能有相应的扩展方法,所以通过这里例子,大家以后要用的话也要谨慎,最起码记住一下两点。
如果扩展方法与该类型中定义的方法具有相同的签名,则扩展方法永远不会被调用。
在命名空间级别将扩展方法置于范围中。 例如,如果你在一个名为 Extensions 的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions; 指令置于范围中。
当然我们再编写程序的时候如果真的不确定一个类我们是否会不会将来去扩展,我们可以使用分部类,这样我们即使要扩展,也可以直接再加一个方法,重新编译,就可以实现了和上边同样的效果,还不会有上边的顾虑。
原文地址:http://blog.csdn.net/lovemenghaibin/article/details/44409603