.NET 中的扩展方法是什么?
编辑:我在扩展方法的使用上发布了一个后续问题
扩展方法允许开发人员向现有 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 中:
(来源: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
正在向 class 添加一个名为 average 的方法Extended
。要获得平均值,请调用average
方法,因为它属于extended
类:
Extended ex = new Extended();
Console.WriteLine(ex.average());
即使您无权访问原始源代码,您也可以为某些东西添加方法。让我们考虑一个例子来解释这一点:
假设我有一条狗。所有的狗——所有类型的狗——做某些事情:
狗能做的事,统称为“方法”。现在让我们假设 OO Heaven 中的 Great Programmer 忘记在 dog 类中添加一个方法:FetchNewspaper()。你希望能够说:
rex.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();
您可以在没有源代码的情况下将方法添加到类中。这非常方便!
扩展方法是开发人员向他们无法控制的对象“添加”方法的方式。
例如,如果您想向 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()”。
总之,这是一种无需继承即可向现有对象添加功能的方法。
扩展方法是一种“编译器技巧”,它允许您模拟将方法添加到另一个类,即使您没有它的源代码。
例如:
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
关键字之前,等等)。
扩展方法实际上并不修改它们看起来正在扩展的类;相反,编译器会破坏函数调用以在运行时正确调用该方法。但是,扩展方法正确地显示在带有独特图标的智能感知下拉列表中,您可以像使用普通方法一样记录它们(如上所示)。
注意:如果已存在具有相同签名的方法,则扩展方法永远不会替换方法。
这是 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
扩展方法是我们可以将方法添加到现有数据类型的技术。下面是我们如何向现有数据类型添加方法的示例。
代码:
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();
}
}
代码:
public static void Main(String[] args)
{
string str = "this is my name punit";
int i = str.LongestWord();
}
关键点:
扩展方法类需要是静态的
扩展方法的第一个参数将具有 this 关键字,并且该方法也应该是静态的
扩展方法是一种特殊的静态方法。它允许我们在现有类型中添加方法,而无需修改现有类型。例如,如果您有 Customer 类,并且您需要在其中添加一个方法而无需在 Customer 类中进行修改,对于这种情况,我们有扩展方法。有关更多示例,请参阅此链接 https://princesid85.wixsite.com/website/home/you-ve-been-holding-your-pen-wrong-your-entire-life
这个问题已经得到解答,但我想补充一点,如果您有另一个项目中的类型并且您不想返回该项目以添加一些功能,这将非常有用。我们正在使用 NHibernate,并且有一个项目用于我们的数据持久层,人们希望保持清洁。为了在这些对象上获得好的和可发现的附加方法,我能够使用扩展方法,它真的让我的一天变得更加美好。
此外,由于没有其他人发布它,这是 MSDN 上一篇关于它的好文章 - http://msdn.microsoft.com/en-us/library/bb383977.aspx
我想我会添加一个更具概念性且更少依赖代码的解释。
想象一辆福特汽车从施工线上滚下来。您无法使用施工线,但您希望所有福特汽车都能够在汽车后部添加额外的扰流板(展示时看起来更酷)。你打算怎么做?在计算世界中,除非您可以使用福特工厂内的原始施工线,否则您不能只是将东西用螺栓固定到福特上。现在你可以:输入扩展方法。
现在您可以执行以下操作:
Ford hilux = new Ford();
hilux.DisplayRearFoiler(); // you can now do this even though you don't have access to the Ford source code.
您必须创建扩展方法。参考上面的答案。
我想用Sealed class来回答扩展方法。
假设您有一个包含重要方法的密封类。您现在想向它添加一个新方法。假设这个类在一个外部 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();
希望您发现扩展方法有用。
C# 中的扩展方法
什么是扩展方法?
Extension method means Class name and method name are having with Static Key word.
使用“this”关键字的扩展方法,应该是第一个签名是提及识别地址,这个类型必须与like相同,
公共静态字符串方法(此字符串i,int j)
和
字符串 res = "ae" .Meth(num);
粗体部分为识别地址。命名空间应该相同。
为什么我们需要扩展?
我们在很多地方都使用相同的功能,之后找不到我们在这里使用的原因。为此使用地址标识。静态意味着单个实例。这只能访问静态成员函数。甚至在静态类中没有静态类方法如何访问?例如:参见“Sal”方法中的抛出错误,
静态类 Emp { public int Sal(int i,int j) { return i * j; } }
仅访问静态成员。和
以下代码我们无法在静态类中为非静态类创建对象。那么如何将非静态方法访问到静态类中。因此,我们遵循不继承的扩展方法。
例如,在此处使用 Extension 方法添加或什至功能,
使用系统。文本;
使用 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();
}
}
结果:
有时我们想将我们自己的附加功能添加到一个类型中,并将它们用作该类型上的常用实例方法。如果我们有源代码,我们可以轻松添加新功能而无需创建扩展方法。但是当我们没有源代码并且仍然想添加和调用附加功能作为类型上的实例方法时,就会出现问题;扩展方法用于将我们自己的功能添加到类型中并在源代码不可用时将它们用作类型上的实例方法。
当我们想要添加我们自己的功能时,我们甚至可以创建一个单独的静态类并在我们的代码中调用它的静态方法,而不是创建扩展方法,但问题可能是代码可读性。
LINQ极大地受益于扩展方法。
它们在开发时非常有用,因为使用 Intellisense 可以很容易地为多个开发人员提供所需的方法;而对于静态方法,我们每次都必须在代码中编写className.MethodName() 。
/// <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;
}
}
}