什么是扩展方法 - 以及它们与其他方法的区别?

时间:2009-04-23 23:10:37

标签: .net extension-methods

  

这个问题已经有了答案:
  What are Extension Methods? 5个答案
  Usage of Extension Methods 9个答案
  What Advantages of Extension Methods have you found? [closed] 30个答案

所以当我阅读.Net和intellisensing(!)时,我经常会遇到“扩展方法”一词......

什么是扩展方法 - 以及它们与其他方法的区别?

7 个答案:

答案 0 :(得分:2)

它们是静态方法,可以在不修改原始类型的情况下添加到其他类型。

例如,假设您希望能够在字符串上调用ToInt()。您可以创建一个这样的方法:

public static int ToInt( this string value ){ return Int32.Parse( value ); }

现在假设你的网页上有一个名为Port的TextBox,你可以像这样得到一个int:

int port = Port.Text.ToInt();

现实世界对扩展方法的使用通常比它更有用,并且被Fluent API和testing框架大量使用。

UPDATE:扩展的另一个好用途是为接口提供类似默认行为的基类。许多流行的测试方法依赖于接口定义和模拟这些接口的能力。不幸的是,基于接口的所有东西都会失去继承的一些好处。扩展方法可以增加基类的一些便利性,而不会污染接口。

例如,假设我有一个Window基类定义如下

public class Window
{
    public void Show( object owner ){...}
    public void Show(){ Show( null ); }
}

现在我想从这个类中提取IWindow接口。我真的不想要求从IWindow派生的每个对象都必须实现第二个Show方法,因为它只是一个基本的重载。所以我可以像这样定义我的界面:

public interface IWindow
{
    void Show( object owner );
}

这样的扩展方法:

public static void Show( this IWindow window )
{
    window.Show( null );
}

答案 1 :(得分:1)

扩展方法是静态方法,第一个参数使用特殊语法。编译器允许您像实例方法一样使用它们。

public class ExampleClass
{
   public String Value { get; set; }
}

现在,您可以通过修改类来引入方法PrintValue()

public class ExampleClass
{
   public String Value { get; set; }

   public void PrintValueInstance()
   {
      Console.WriteLine(this.Value);
   }
}

您还可以在某些类中创建静态方法 - ExampleClass或任何其他类。

public class AnyClass
{
   public static void PrintValueStatic(ExampleClass exampleClass)
   {
      Console.WriteLine(exampleClass.Value);
   }
}

你可以创建一个扩展方法 - 它很像静态方法,但用this标记第一个参数。

public class ExtensionClass
{
   public static void PrintValueExtension(this ExampleClass exampleClass)
   {
      Console.WriteLine(exampleClass.Value);
   }
}

然后如下:

ExampleClass example = new ExampleClass();

example.PrintValueInstance(); // Instance method

AnyClass.PrintValueStatic(example); // Static method

ExtensionClass.PrintValueExtension(example); // Extension method (long usage)

example.PrintValueExtension(); // Extension method

因此,编译器允许您对与第一个参数的类型匹配的对象使用带有实例方法语法的静态方法。这允许您向类添加方法,而无需修改类。当然,存在一个限制 - 您只能从扩展方法中访问公共成员。

您还可以定义接口的扩展方法,然后它们可用于实现接口的所有类。

public interface ISomeInterface
{
   Int32 Foo(Int32 value);
   Int32 Bar(String text);
}

public static class SomeInterfaceExtension
{
    public static Int32 FooFooBar(this ISomeInterface @this, String text)
    {
       return  @this.Foo(@this.Foo(@this.Bar(text));
    }
}

现在,方法FooFooBar()可用于实现ISomeInterface的所有类。

public class NiceClass : ISomeInterface
{
   public Int32 Foo(Int32 value)
   {
      return value * value;
   }

   public Int32 Bar(String text)
   {
      return text.Length;
   }
}

现在,您可以在NiceClass实例上使用扩展方法。

NiceClass niceClass = new NiceClass();

Console.WriteLine(niceClass.FooFooBar("ExtensionMethodExample"));

答案 2 :(得分:0)

请参阅有关扩展方法的MSDN Topic

答案 3 :(得分:0)

扩展方法是您自己的类中的静态方法,可用于操作类型,通常不在您自己的代码中。

例如,您可以写:

public static void RemoveS(this string value)
{
   value = value.Trim("s");
}

此方法将附加到系统中的所有“字符串”类型,只要编写它的命名空间可供编译器使用。

像:

string foo = "Somethings";
string betterfoo = foo.RemoveS();

请参阅:http://www.csharphelp.com/archives/archive148.html以获取更多帮助。

答案 4 :(得分:0)

我在这里写了一篇关于它们的摘要:

http://blogs.msdn.com/vbteam/archive/2007/01/05/extension-methods-part-1.aspx

当我以前在VB编译团队工作时。它很好地概述了它们有用的原因。

答案 5 :(得分:0)

扩展方法是您为扩展已存在的类型(字符串,整数,字符或自定义类型)而创建的方法。

这允许您为其他人创建的内置或类型添加功能(例如在dll中)。

答案 6 :(得分:0)

扩展方法添加到静态类的静态函数,编译器可以允许您将这些静态函数作为ANOTHER类型的实例方法公开。例如,假设我想向MakeInvisible()类添加一个名为“Control”的函数,该函数可以使其不可见(忽略“Hide()中已存在此类方法的事实}” ......)。我会这样做。

public static class ControlExtensionClass
{
    public static void MakeInvisible(this Control control)
    {
        control.Visible = false;
    }
}

如果我在引用的程序集中的某处有这个类,那么我可以在任何地方执行此操作..

Control c;

c.MakeInvisible();

this”关键字是使其成为扩展方法的原因。这告诉编译器将此方法添加到Control类,并提供对指定变量中实体的引用。