什么是扩展方法?

问题描述 投票:41回答:10

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

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

.net extension-methods
10个回答
55
投票

扩展方法允许开发人员向现有CLR类型的公共协定添加新方法,而无需对其进行子类化或重新编译原始类型。

扩展方法有助于将当今动态语言中流行的“duck typing”支持的灵活性与强类型语言的性能和编译时验证相结合。

参考: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-\.]+@([\w-]+\.)+[\w-]{2,4}$");
    return regex.IsMatch(s);
}

现在,可以直接从任何字符串调用上述方法,如:

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

添加的方法也会出现在IntelliSense中:

alt text (来源:scottgu.com

关于扩展方法的实际用法,您可以在不派生新类的情况下向类添加新方法。

看一下下面的例子:

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的方法。要获得平均值,请调用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/


0
投票

有时我们希望将自己的附加功能添加到类型中,并将它们用作该类型的常用实例方法。如果我们有源代码,我们可以轻松添加新功能而无需创建扩展方法。但是当我们没有源代码并且仍然想要在类型上添加和调用附加功能作为实例方法时会出现问题;扩展方法用于将我们自己的功能添加到类型中,并在源代码不可用时将它们用作类型的实例方法。

当我们想要添加自己的功能时,我们甚至可以创建一个单独的静态类,并在我们的代码中调用它的静态方法,而不是创建扩展方法,但问题可能是代码可读性。

LINQ从扩展方法中受益匪浅。

它们在开发时非常有用,当使用Intellisense可以轻松地向多个开发人员提供所需的方法时;使用静态方法时,我们每次都必须在代码中编写className.MethodName()。


0
投票

扩展方法是我们可以向现有数据类型添加方法的技术。下面是我们如何向现有数据类型添加方法的示例。

  1. 我们创建了一个扩展方法类,我们在其中创建了各种扩展方法

码:

public static class ExtensionMethods
{
    public static int WordCount(this string str)
    {
        return str.Split(' ').Count();
    }

    public static int LongestWord(this string str)
    {
        return str.Split(' ').Select(x =>
                x.Length).OrderByDescending(y =>
                y).FirstOrDefault();
    }
}
  1. 下面是我们调用上面类中指定的扩展方法的程序类。

码:

public static void Main(String[] args)
{
    string str = "this is my name    punit";
    int i = str.LongestWord();
}

关键点:

  • 扩展方法类需要是静态的
  • extension方法的第一个参数将包含此关键字,该方法也应该是静态的

11
投票

扩展方法 - 简单解释

假设我有一只狗。所有的狗 - 所有类型的狗的动物 - 做某些事情:

  1. WagsTail
  2. 喊“Woof!”
  3. 摇爪等

狗可以做的事情都被称为“方法”。

现在让我们假设OO Heaven中的伟大程序员忘记为dog类添加一个方法:FetchNewspaper()。你希望能够说:

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

......即使您无法访问源代码。

你是如何让你的狗这样做的?您唯一的解决方案是创建“扩展方法”。

创建扩展方法

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

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

如果你想让你的狗得到报纸,只需这样做:

Dog freddie_the_family_dog = new Dog();

freddie_the_family_dog.FetchNewspaper();

您可以在没有源代码的情况下将方法添加到类中。这非常方便!


6
投票

扩展方法是开发人员将方法“添加”到无法控制的对象的方法。

例如,如果要向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()”。

总之,它是一种在没有继承的情况下向现有对象添加功能的方法。


5
投票

扩展方法是一种“编译器技巧”,允许您模拟向另一个类添加方法,即使您没有它的源代码。

例如:

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关键字之前,等等)。

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

注意:如果已存在具有相同签名的方法,则扩展方法永远不会替换方法。


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


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
投票

我想根据Sealed类来回答扩展方法。

假设您有一个包含重要方法的密封类。您现在想要为其添加新方法。假设此类包含在外部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;
    }
}

我已经将名为Average的公共静态方法添加到新的静态类中。此方法具有主类的参数,前面带有'this'关键字。

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

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

希望您发现扩展方法有用。


0
投票

C#中的扩展方法

什么是扩展方法?

Extension method means Class name and method name are having with Static Key word.

使用“this”关键字的扩展方法应该是第一个签名是提到识别地址,这种类型必须是相同的,

public static string Meth(this string i,int j)

string res =“ae”.Meth(num);

粗体部分是识别地址。命名空间应该相同。

为什么我们需要扩展?

我们在很多地方使用相同的功能,之后找不到我们在这里使用的原因。出于这个原因,使用地址识别。静态意味着单个实例。这只能访问静态成员函数。甚至如何在Static类中没有静态类方法进行访问?例如:在“Sal”方法中看到抛出错误,

static class Emp {public int Sal(int i,int j){return i * j; }}

仅访问静态成员。和

enter image description here

以下代码我们无法在静态类中为非静态类创建对象。那么如何将非静态方法访问到静态类中。因此,我们遵循Extension方法而不继承。

例如,使用Extension方法添加或偶数功能,

使用系统。文本;

使用System.Threading.Tasks;

namespace Extension_Method {static class Program {

    public static string Meth (this string i,int j)
    {
        if (j % 2 == 0)
        {
            return "Even";
        }
        else
        {
            return "ODD";

        }
    }


}
class program2
{
    static void Main (string [] args)
    {
        Console. WriteLine ("Enter Integer");
        int num = Convert.ToInt32(Console.ReadLine());

        string res = "ae".Meth(num);

        Console. WriteLine(res);
        Console.ReadLine();
    }
}

结果:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.