如何使用c#扩展方法扩展类?


98

扩展方法可以应用于该类吗?

例如,将DateTime扩展为包括一个Tomorrow()方法,该方法可以像下面这样调用:

DateTime.Tomorrow();

我知道我可以用

static DateTime Tomorrow(this Datetime value) { //... }

要么

public static MyClass {
  public static Tomorrow() { //... }
}

得到类似的结果,但是如何扩展DateTime以便调用DateTime.Tomorrow?

Answers:


70

除非将现有类型标记为部分类型,否则不能将方法添加到现有类型,只能通过扩展方法添加看起来是现有类型的成员的方法。由于这种情况,您不能将静态方法添加到类型本身,因为扩展方法使用该类型的实例。

没有什么可以阻止您创建自己的静态帮助器方法,如下所示:

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

您将这样使用:

DateTime tomorrow = DateTimeHelper.Tomorrow;

6
呵呵?除非在此之后的6个月内实施了该解决方案,并且Kumu的回答就在那里,否则这实际上是不完整的!
cregox 2012年

4
@Cawas这还不完整,Andrew展示了如何使用静态助手而不是扩展方法(因为没有实例)来执行此操作。
Nick N.

1
你说得对,尼克。我确实更喜欢扩展方法!;)
cregox

2
关于extensionmethod.net/csharp/datetime呢?恕我直言,使学习曲线最小化的更好示例是具有完整源代码和良好模式的真实应用程序
Kiquenet 2014年

3
此代码的问题在于它仅适用于DateTime.Now而不适用于任何DateTime对象。作为一种实用程序,可能需要使用它来确定前一天(或将来)的第二天。更不用说DateTime.Now每次您确定时都确定...
MintGrowth 2015年

181

使用扩展方法

例如:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

用法:

DateTime.Now.Tomorrow();

要么

AnyObjectOfTypeDateTime.Tomorrow();

2
舒吉的答案也为解决这一问题提供了一些思路。
cregox 2012年

8
不要忘记“使用ExtensionMethods;” 为此,请在文档的顶部。
路加·阿德顿

为什么我不能做DateTime.Tomorrow()?
lawphotog 2014年

嗨lawphotog,此扩展程序需要一个对象,此处的DateTime是结构而不是对象。
Kumu 2014年

4
正如前面的评论中提到的那样(显然,这对我来说还不够清楚),您将无法使用DateTime.Tomorrow()扩展方法,仅适用于类和类结构的INSTANCES。要在类结构上“扩展”静态方法,请遵循Andrew的回答Shuggy的回答
亚历克斯(Alex)

18

扩展方法是语法语法,用于使第一个参数是T类型的实例的静态方法看起来像它们是T上的实例方法。

这样,您在制作“静态扩展方法”时的利益就大大丧失了,因为它们比扩展方法更会使代码阅读者困惑(因为它们看起来是完全合格的,但实际上并未在该类中定义)没有语法上的收获(例如,能够在Linq中以流畅的样式链接呼叫)。

由于无论如何都必须通过使用将扩展引入范围,所以我认为创建起来更简单,更安全:

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

然后通过以下方式在您的代码中使用它:

WriteLine("{0}", DateTimeUtils.Tomorrow)

11

我能找到的最接近的答案是将扩展方法添加到System.Type对象中。不漂亮,但仍然很有趣。

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

否则,IMO Andrew和ShuggyCoUk会有更好的实现。


这种方法存在问题。必须键入“ typeof(...)”并不方便,并且通过智能感知,您将看到每种类型的扩展名。不过,这是我从未想到的一种有趣的方法,即+1。
Meta-Knight

@ Meta-Knight是的,这就是为什么我个人更喜欢对方的回答。我的答案将具有与OP问题最接近的语法,但这不是解决此问题的最佳方法。
阿德里安·高东

Type可以替换为所需的任何其他类型。我使用它,From它完美地工作。所以我想这个答案是一般性的但正确的
Katia 2015年

3

我会和Kumu一样

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

但是像这样新的DateTime()。Tomorrow();

认为它比DateTime.Now.Tomorrow();的观看次数更多。


1
而且您错过了将它写成对Kumu答案的评论的机会!:P
cregox 2012年

3

它们提供了通过添加新方法而无需修改类型来扩展现有类型的功能。使用实例方法语法从应用程序中的扩展类型的对象中调用方法称为“扩展”方法。扩展方法不是该类型的实例成员。要记住的关键点是,仅当通过using指令将名称空间显式导入到应用程序源代码中时,扩展方法(定义为静态方法)才在范围内。即使扩展方法被定义为静态方法,它们仍然使用实例语法来调用。

在此处查看完整的示例 http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

例:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }

3

我在寻找类似的东西-提供扩展方法的类的约束列表。似乎很难找到一个简洁的清单,所以去了:

  1. 您不能有任何私有或受保护的任何东西-字段,方法等。

  2. 它必须是一个静态类,如中所述public static class...

  3. 只有方法可以在该类中,并且它们都必须是公共静态的。

  4. 您不能使用常规的静态方法-不允许使用不包含this参数的方法。

  5. 所有方法都必须开始:

    公共静态ReturnType MethodName(this ClassName _this,...)

因此,第一个参数始终是this引用。

这会产生一个隐式问题-如果您添加需要任何类型的锁的方法,则无法在类级别上真正提供它。通常,您会提供一个私有实例级别的锁,但是不可能添加任何私有字段,从而给您提供一些非常尴尬的选项,例如在某些外部类上将其作为公共静态变量提供,等等。C#语言的标志在这些设计中出现了严重的转变

解决方法是将Extension Method类用作常规类的Facade,并且Extension类中的所有静态方法都可能使用Singleton调用真实类。


2

不幸的是,你不能那样做。我相信这将是有用的。键入更自然:

DateTime.Tomorrow

比:

DateTimeUtil.Tomorrow

对于Util类,您必须检查两个不同类(而不是一个)中是否存在静态方法。


1

我们通过详细说明改进了答案。现在,更容易理解扩展方法

扩展方法:这是一种机制,通过它我们可以扩展现有类的行为,而无需使用子类或修改或重新编译原始类或结构。

我们可以扩展自定义类,.net框架类等。

扩展方法实际上是在静态类中定义的一种特殊的静态方法。

由于DateTime上面已经讲授了课程,因此我们没有上这堂课了。

以下是示例

//这是现有的Calculator类,只有一个方法(添加)

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.