2008-12-31 148 views
38

.NET中的扩展方法是什么?什么是扩展方法?



编辑: 我已经发布了一个跟进的问题在Usage of Extension Methods

+1

对于你的后续行动,请参阅下面的答案。 基本上你会创建扩展而不是使用继承。 – 2008-12-31 17:47:01

+0

@汤姆安德森 - 所以创建扩展方法的决定主要基于对源代码的访问?我的情况是 – Developer 2008-12-31 17:49:54

+1

。 另一个实例很容易,而不是从System.Windows.Forms.Form继承,然后添加方法,然后修改我的所有源以使用该基类,我只需编写该扩展,现在所有表单都具有该扩展。 – 2008-12-31 17:52:37

回答

50

扩展方法允许开发新的方法添加到现有的CLR类型, 的公共 合同,而无需子类,或 重新编译的原始类型。

扩展方法帮助混合的 灵活性的“鸭打字”支持 今天 动态语言中流行的性能和编译时强类型语言 的 验证。

参考:http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx

下面是一个扩展方法的一个样品(注意第一参数的this关键字盈):

public static bool IsValidEmailAddress(this string s) 
{ 
    Regex regex = new Regex(@"^[\w-\.][email protected]([\w-]+\.)+[\w-]{2,4}$"); 
    return regex.IsMatch(s); 
} 

现在,上面的方法可以被称为直接从任何字符串,像这样:

bool isValid = "[email protected]".IsValidEmailAddress(); 
然后

添加的方法也将出现在智能感知:

alt text http://www.scottgu.com/blogposts/extensionmethods/step1.jpg

至于用于扩展方法实际使用,您可以添加新的方法,一类没有派生新类。

看看下面的例子:

public class Extended { 
    public int Sum() { 
     return 7+3+2; 
    } 
} 

public static class Extending { 
    public static float Average(this Extended extnd) { 
     return extnd.Sum()/3; 
    } 
} 

正如你所见,类Extending是加入一个名为平均法Extended类。为了得到平均,你叫average方法,因为它属于extended类:

Extended ex = new Extended(); 

Console.WriteLine(ex.average()); 

参考:http://aspguy.wordpress.com/2008/07/03/a-practical-use-of-serialization-and-extension-methods-in-c-30/

5

扩展方法的方式为开发商的“附加”方法,他们无法控制的对象。例如,如果您想为System.Windows.Forms对象添加一个“DoSomething()”方法,因为您无法访问该代码,您只需为该表单创建一个扩展方法以下语法。

Public Module MyExtensions 

    <System.Runtime.CompilerServices.Extension()> _ 
    Public Sub DoSomething(ByVal source As System.Windows.Forms.Form) 
     'Do Something 
    End Sub 

End Module 

现在您可以在表单中调用“Me.DoSomething()”。

总之,它是一种向现有对象添加功能而无需继承的方法。

3

扩展方法是“编译器把戏”,让您可以模拟加方法到另一个类,即使你没有它的源代码。

例如:

using System.Collections; 
public static class TypeExtensions 
{ 
    /// <summary> 
    /// Gets a value that indicates whether or not the collection is empty. 
    /// </summary> 
    public static bool IsEmpty(this CollectionBase item) 
    { 
     return item.Count == 0; 
    } 
} 

从理论上讲,所有集合类现在包括IsEmpty方法,如果方法没有项目(前提是你已经包括定义上述类的命名空间),则返回true。

如果我错过了任何重要的东西,我肯定有人会指出。 (请!)

当然,也有关于扩展方法的声明(他们必须是静态的,第一个参数必须由this关键字来preceeded,等等)的规则。

扩展方法实际上并不修改它们看起来正在扩展的类;相反,编译器会破坏函数调用,以便在运行时正确调用该方法。但是,扩展方法正确显示在具有独特图标的智能感知下拉列表中,并且您可以像正常方法一样记录它们(如上所示)。

注:扩展方法从未替代的方法,如果方法已经具有相同签名存在。

1

下面是VB.Net中的示例;注意Extension()属性。将其放置在项目的模块中。

Imports System.Runtime.CompilerServices 
<Extension()> _ 
Public Function IsValidEmailAddress(ByVal s As String) As Boolean 
    If String.IsNullOrEmpty(s) Then Return False 

    Return Regex.IsMatch(email, _ 
     "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$") 
End Function 
0

这个问题已经回答了,但我想补充一点,这是非常有用的,如果你有是另一个项目内的类型,你不想回到那个项目为了添加一些功能。我们使用NHibernate并为我们的数据持久层提供了一个项目,这些人员都希望保持清洁。为了在这些对象上获得更好的和可发现的附加方法,我可以使用扩展方法,它真的让我的一天变得更加美好。

而且,因为没有其他人贴吧,这里有关于它的MSDN一个很好的文章 - http://msdn.microsoft.com/en-us/library/bb383977.aspx

7

为什么我写另外一个答案?

上述答案太复杂。我猜如果你需要问什么是扩展方法,你不会真正知道什么是(i)公共契约,(ii)CLR,(iii)类型,(iv)子类,( v)鸭打字等

让我们保持它的简单 - 扩展方法解释

假如我有一只狗。狗是一种“类型”的动物。所有的狗 - 类犬的所有动物 - 做某些事情:

  1. WagsTail
  2. 呼喊
  3. 震撼爪子等

的东西,狗可以“汪!”这些都是所谓的“方法”。

现在让我们假设OO天堂的伟大程序员忘了给狗类添加一个方法。假设你想让你家里的所有狗做额外的事情:FetchNewspaper。

你要能够说:

rex.FetchNewspaper(); // or 
wolfie.FetchNewspaper(); // or 
beethoven.FetchNewspaper(); 

......即使你没有访问源代码。沃尔夫,雷克斯和贝多芬是你宠物家庭中的狗。

你最近怎样才能让你的狗做到这一点?

您将不得不重新编译。但是你没有源代码!如果您没有源代码,则无法将该方法添加到代码中的相关位置。

你唯一的解决方法是创建一个“扩展方法”。

创建扩展方法

(注意:在下面的第一个参数前面的“this”关键字):

public static void FetchNewsPaper(this Dog familyDog) 
{ 
    ConsoleWriteline(“Goes to get newspaper!”) 
} 

如果你想你的狗拿到报纸仅仅做到这一点:

Dog freddie_the_family_dog = new Dog(); 

freddie_the_family_dog.FetchNewspaper(); 

如果没有扩展方法,那么你就不能问Freddie_the_family_dog到FETC h报纸。

我们刚刚做了什么?

我们增加了一个额外的方法,让所有的狗都有能力取得报纸。

它是如何工作的?

你只是:(i)打电话给你的狗,和(ii)告诉他取纸。你不能做的就是说“取一张报纸”,而不指定你家里的哪只狗应该抓取。

我希望能帮到你。如果您在发表评论时仍有问题,我会尽我所能解释。

0

我想我会添加一个更具概念性和较少依赖代码的解释。

想象一下福特公司正在推出施工线。您无法进入施工生产线,但您希望所有福特汽车能够在汽车后部增加一个扰流板(展示时看起来更酷)。你打算怎么做?在计算世界中,除非你有机会接触到福特工厂的原始生产线,否则你不能只是把东西拉向福特。那么现在你可以:输入扩展方法。

现在你可以做这样的事情:

Ford hilux = new Ford(); 

hilux.DisplayRearFoiler(); // you can now do this even though you don't have access to the Ford source code. 

你必须创建扩展方法。参考上面的答案。

0

我想根据密封类回答扩展方法。

假设你有一个密封类包含重要的方法。你现在想要为它添加一个新的方法。假设这个类来自一个外部DLL,所以你不能添加一个新的方法。你会做什么 ?

举另一个例子。假设该类是由项目经理或安全专家构建在您的应用程序中的。只有获得项目经理或安全专家的许可,才能编辑该课程。

您的解决方案可能是从此类中删除密封关键字,并且 会在其他类中继承它。然后在子类(继承这个类)内部,你可以添加你的新方法。

但等待 - >您不能简单地删除密封关键字,因为这可能会危及整个应用程序的安全性。我可以打赌你的PM或安全专家永远不会以安全问题给你这个权限。

那么在这里可以做些什么?

答案是扩展方法它可以添加在一个静态类,你甚至不需要再触摸密封类。

例子: -

sealed class MyData 
{ 
    private double D1, D2, D3; 
    public MyData(double d1, double d2, double d3) 
    { D1 = d1; D2 = d2; D3 = d3; } 
    public double Sum() { return D1 + D2 + D3; } 
} 

static class ExtendMyData 
{ 
    public static double Average(this MyData md) 
    { 
     return md.Sum()/3; 
    } 
} 

我加入了一个名为平均到一个新的静态类中的公共静态方法。该方法的前面带有'this'关键字的主类的参数。

现在要调用Average方法,我使用父级密封类的对象而不是子类。

MyData md = new MyData(3, 4, 5); 
double exAverage = md.Average(); 

希望你找到扩展方法有用。