什么是扩展方法?

时间:2008-12-31 17:24:30

标签: .net extension-methods

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



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

13 个答案:

答案 0 :(得分:55)

  

扩展方法允许开发人员向公众添加新方法   现有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-\.]+@([\w-]+\.)+[\w-]{2,4}$");
    return regex.IsMatch(s);
}

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

bool isValid = "so@mmas.com".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/

答案 1 :(得分:11)

扩展方法 - 简单说明

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

  1. WagsTail
  2. 喊“Woof!”
  3. Shakes Paw等
  4. 狗可以做的事情都被称为“方法”。

    现在让我们假设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();
    

    您可以将方法添加到类而无需源代码。这非常方便!

答案 2 :(得分: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()”。

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

答案 3 :(得分: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下拉列表中正确显示,您可以像普通方法一样记录它们(如上所示)。

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

答案 4 :(得分: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

答案 5 :(得分:1)

扩展方法是一种特殊的静态方法。它允许我们在现有类型中添加方法而无需修改该现有类型。 例如。如果您有Customer类,并且需要在其中添加一个方法,而无需在Customer类中进行修改,那么对于这种情况,我们有扩展方法。 请参阅此链接以获取更多示例 https://princesid85.wixsite.com/website/home/you-ve-been-holding-your-pen-wrong-your-entire-life

答案 6 :(得分:0)

这个问题已经得到了解答,但是我想补充一点,如果你的类型在另一个项目中并且你不想回到那个项目来添加一些功能。我们正在使用NHibernate并为我们的数据持久层创建一个项目,让人们保持干净。为了在这些对象上获得漂亮且可发现的附加方法,我能够使用扩展方法,这真的让我的日子更加美好。

此外,由于没有其他人发布过它,这里有一篇关于MSDN的好文章 - http://msdn.microsoft.com/en-us/library/bb383977.aspx

答案 7 :(得分:0)

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

想象一下福特推出了建设线。您无法使用施工线,但您希望所有福特汽车都能够在汽车后部添加额外的扰流板(在展示时看起来更凉爽)。你打算怎么做?在计算机领域,除非您能够访问福特工厂内的原始施工线,否则您不能只是向福特汽车采购螺栓。那么你现在可以:输入扩展方法。

现在你可以这样做:

Ford hilux = new Ford();

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

您必须创建扩展方法。请参阅上述答案。

答案 8 :(得分:0)

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

假设您有一个密封类,其中包含重要方法。您现在想要为其添加新方法。假设此类包含在外部DLL中,因此您无法向其中添加新方法。你会做什么 ?

再举一个例子。假设您的项目经理或安全大师在您的应用程序中构建了该类。您只能在获得项目经理或安全大师的许可后才能编辑该课程。

  

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

但等等 - &gt;您不能简单地删除密封关键字,因为这可能会危及整个应用程序的安全性。我敢打赌,你的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();

希望您找到有用的扩展方法。

答案 9 :(得分: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”方法中看到抛出错误,

静态类Emp     {         public int Sal(int i,int j)         {             返回i * j;         }     }

仅访问静态成员。并且

enter image description here

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

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

使用System。文本;

使用System.Threading.Tasks;

命名空间Extension_Method {     静态类程序     {

    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

答案 10 :(得分:0)

有时候,我们想向类型添加自己的附加功能,并在该类型上将它们用作常规实例方法。如果我们拥有源代码,则可以轻松添加新功能而无需创建扩展方法。但是,当我们没有源代码并且仍想添加和调用其他功能作为类型的实例方法时,就会发生问题。扩展方法用于将我们自己的功能添加到类型中,并在源代码不可用时用作类型上的实例方法。

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

LINQ 受益于扩展方法。

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

答案 11 :(得分: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();
}

要点:

  • 扩展方法类必须是静态的

  • 扩展方法的第一个参数将具有此关键字,并且该方法也应该是静态的

答案 12 :(得分:0)

/// <summary>
/// External Library Code
/// </summary>
namespace ExternalLibrary
{
    public class Calculator
    {
        public int Number1 { get; set; }
        public int Number2 { get; set; }

        public int Addition()
        {
            return Number1 + Number2;
        }

        public int Subtraction()
        {
            return Number1 - Number2;
        }
    }
}

using ExternalLibrary;
using System;

namespace StackOverFlow
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculator calc = new Calculator()
            {
                Number1 = 5,
                Number2 = 3
            };
            Console.WriteLine(calc.Addition());
            Console.WriteLine(calc.Subtraction());

            // Here we want multiplication also. but we don't have access Calculator
            // class code, so we can't modify in that.
            // In order to achieve this functionality we can use extension method.
            Console.WriteLine(calc.Multiplication());

            Console.ReadLine();
        }
    }

    /// <summary>
    /// Extension Method for multiplication
    /// </summary>
    public static class CalculatorExtension
    {
        public static int Multiplication(this Calculator calc)
        {
            return calc.Number1 * calc.Number2;
        }
    }
}