【问题标题】:How do I extend a class with c# extension methods? [duplicate]如何使用 c# 扩展方法扩展类? [复制]
【发布时间】:2010-11-14 08:45:50
【问题描述】:

类可以应用扩展方法吗?

例如,扩展 DateTime 以包含一个 Tomorrow() 方法,该方法可以像这样调用:

DateTime.Tomorrow();

我知道我可以使用

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

或者

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

对于类似的结果,但如何扩展 DateTime 以便可以调用 DateTime.Tomorrow?

【问题讨论】:

    标签: c# extension-methods


    【解决方案1】:

    使用extension method

    例如:

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

    用法:

    DateTime.Now.Tomorrow();
    

    AnyObjectOfTypeDateTime.Tomorrow();
    

    【讨论】:

    • Shuggy's answer 也揭示了解决此问题的类似方法。
    • 不要忘记'使用 ExtensionMethods;'在您的文档顶部。
    • 为什么我不能做 DateTime.Tomorrow()?
    • 嗨 lawphotog,这个扩展需要一个对象,这里 DateTime 是一个结构体而不是一个对象。
    • 正如之前的 cmets 中提到的(显然对我来说还不够清楚),您将无法使用 DateTime.Tomorrow(),因为扩展方法仅适用于类的实例和类结构。要在类结构上“扩展”静态方法,请遵循 Andrew's answerShuggy's answer
    【解决方案2】:

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

    没有什么能阻止您像这样创建自己的静态辅助方法:

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

    你会这样使用:

    DateTime tomorrow = DateTimeHelper.Tomorrow;
    

    【讨论】:

    • 嗯?除非它在这之后的 6 个月内实施并且Kumu's answer 就在那里,否则这看起来实际上是不完整的!
    • @Cawas 这并不完整,Andrew 正在展示如何使用静态助手而不是扩展方法(因为没有实例)来做到这一点。
    • 你是对的,尼克。不过,我确实更喜欢扩展方法! ;)
    • extensionmethod.net/csharp/datetime 怎么样? 恕我直言,用于最小化学习曲线的更好样本是具有完整源代码和良好模式的真实应用程序
    • 这段代码的问题是它只适用于 DateTime.Now 而不是任何 DateTime 对象。作为一种实用程序,人们可能希望使用它来确定前一天(或未来一天)之后的一天。更不用说 DateTime.Now 每次调用时都会确定...
    【解决方案3】:

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

    因此,在您制作“静态扩展方法”时,好处很大程度上丧失了,因为它们比扩展方法更容易混淆代码的读者(因为它们似乎是完全限定的,但实际上并未在该类)没有语法增益(例如,能够在 Linq 中以流畅的风格链接调用)。

    由于无论如何您都必须使用 using 将扩展纳入范围,所以我认为创建它更简单、更安全:

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

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

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

    【讨论】:

      【解决方案4】:

      我能得到的最接近答案的方法是将扩展方法添加到 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 没错,这就是为什么我个人更喜欢对方的答案。我的答案将具有最接近 OP 问题的语法,但这不是解决此问题的最佳方法。
      • Type 可以替换为所需的任何其他类型。我将它与From 一起使用,并且效果很好。所以我想这个答案是普遍但正确的
      【解决方案5】:

      我会和 Kumu 做同样的事情

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

      但是这样称呼它 new DateTime().Tomorrow();

      认为它比 DateTime.Now.Tomorrow() 更受欢迎;

      【讨论】:

      • 您错过了将其作为对 Kumu 答案的评论的机会! :P
      【解决方案6】:

      它们提供了通过添加新方法来扩展现有类型的能力,而无需对类型进行任何修改。在应用程序中使用实例方法语法从扩展类型的对象调用方法称为“扩展”方法。扩展方法不是该类型的实例成员。 要记住的关键点是,定义为静态方法的扩展方法仅在命名空间通过 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;
              }
          }
      

      【讨论】:

        【解决方案7】:

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

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

        2. 必须是静态类,如public static class...

        3. 类中只能有方法,而且必须都是public static。

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

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

          public static ReturnType MethodName(this ClassName _this, ...)

        所以第一个参数始终是 this 引用。

        这会产生一个隐含的问题 - 如果您添加需要任何类型的锁的方法,您就无法真正在类级别提供它。通常你会提供一个私有的实例级锁,但不可能添加任何私有字段,给你留下一些非常尴尬的选择,比如在一些外部类上将它作为公共静态提供,等等。变得冒险。签到the C# language had kind of a bad turn in the design for these

        解决方法是使用扩展方法类作为普通类的外观,扩展类中的所有静态方法只调用真实类,可能使用a Singleton

        【讨论】:

          【解决方案8】:

          很遗憾,您不能这样做。不过,我相信它会很有用。打字更自然:

          DateTime.Tomorrow
          

          比:

          DateTimeUtil.Tomorrow
          

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

          【讨论】:

            【解决方案9】:

            我们已经通过详细的解释改进了我们的答案。现在更容易理解扩展方法

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

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

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

            由于DateTime类已经在上面上课了,所以我们没有拿这堂课来解释。

            下面是例子

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

            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)
            
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-05-12
              • 1970-01-01
              • 1970-01-01
              • 2020-04-15
              • 2011-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-09
              相关资源
              最近更新 更多