3

我们可以在扩展方法和继承之间建立某种关系吗?

或者是类似于new在 C# 中使用 -keyword 的扩展方法?

4

4 回答 4

9

对这两个问题都没有。扩展方法实际上是将扩展操作的对象作为第一个参数的方法。

new关键字用于为类的实例分配资源。扩展方法对实例进行操作,但不能充当新替换,这仅仅是因为它需要一个实例(或null该类型的)作为第一个参数。

考虑:

public static class StringExtensions
{
    public static string Reverse(this string _this)
    {
        // logic to reverse the string
    }
}

您可以通过两种方式调用此静态方法:

// as an extension method:
string s = "hello world";
string t = s.Reverse();

// as a static method invocation:
string t = StringExtensions.Reverse(s);

在任何一种情况下,编译器都会更改 MSIL 中的调用以映射第二个调用。编译后,如果没有this-keyword,您将无法从静态对应的扩展方法中识别出扩展方法。

总结

  • 扩展不是类的一部分
  • 扩展与继承无关,实际上是静态方法,不被继承
  • 扩展不能new关键字那样实例化类(但在方法内部你当然可以实例化类)。
  • 扩展可以对 进行操作null,否则该类的方法会引发NullReferenceException. 这是因为实例只是静态方法中的第一个参数。
  • 可以扩展密封类(string如上),这是通过继承无法实现的(不能从密封类派生)。

编辑:
Tigran 和 Floran 暗示这个问题是关于new modifier的,我补充说它甚至可能是关于new generic constraint的。

扩展方法与关键字的任何一个含义都没有关系。new然而,这里有一些彼此相关的想法。我希望它不会使事情更加混乱。如果是这样,请坚持“编辑”上方的部分;)

  • 在新的修饰符上:

    • new 修饰符用于隐藏现有方法。扩展方法永远不能隐藏现有方法,因为声明是静态方法。当您这样做时,您甚至不会收到编译时警告或错误。
    • new 修饰符要求方法(或属性)已经存在并且可以访问。仅当具有相同签名的方法不存在时,扩展方法才能工作。
    • new 修饰符通过继承对类的扩展进行操作,即每个方法都已被继承。扩展方法对类的实例进行操作,与类没有继承关系。
       
  • 关于新的通用约束:

    • 该约束将允许的泛型类型限制为具有可访问的无参数构造函数的泛型类型。扩展方法与泛型无关。
    • 扩展方法本身是泛型的,并且参数(即它所操作的允许的类)可以受到新的泛型约束的限制:

      // this ext. method will only operate on classes that inherit 
      // from ICollectible and have a public parameterless constructor
      public static int CalculateTotal<T>(this T _collectible)
          where T : ICollectible, new()
      {
          // calculate total
      }
      
于 2012-04-08T16:45:58.987 回答
3

不,扩展方法只是扩展现有类的功能。

扩展方法使您能够将方法“添加”到现有类型,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

请参阅MSDN 上的扩展方法(C# 编程指南)

需要该new关键字才能允许您override从基类中使用非虚拟和静态方法。

public class A
{
   public virtual void One();
   public void Two();
}

public class B : A
{
   public override void One();
   public new void Two();
}

B b = new B();
A a = b as A;

a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B

在vs上查看此链接newoverride

于 2012-04-08T16:48:47.400 回答
1

不。扩展方法是一个单独的静态类的语法糖,它的第一个参数是被“扩展”类型的对象。它根本与继承无关。该方法只能访问“扩展”类的公共成员,就像任何其他类一样。

于 2012-04-08T16:46:12.013 回答
0

扩展方法与继承或new关键字(或构造函数)无关。如果您想向没有源代码的类添加一些功能,它们可以提供更好的代码。如果您确实有源代码,它也可以工作,但通常最好只更改源代码。

例如,您可能希望能够这样做:

string text = "this is my string";
int count = text.WordCount();

类中不存在此方法String,您需要这样做:

string text = "this is my string";
int count = MyCommon.WordCount(text);

whereWordCount()是您的某种通用库中的静态方法。

但是使用扩展方法,您也可以这样做:

public static class MyExtensions
{
    public static int WordCount(this String str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, 
                         StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

然后text.WordCount()就像在String类中定义的普通方法一样工作。它只是让事情变得更好用。

这里获取的代码我也建议阅读。

于 2012-04-08T19:49:32.300 回答