我是c#中扩展方法的粉丝,但还没有成功地将扩展方法添加到静态类中,比如Console。

例如,如果我想添加一个名为“WriteBlueLine”的扩展到控制台,这样我就可以:

Console.WriteBlueLine("This text is blue");

我尝试通过添加一个本地的公共静态方法,并将Console作为“this”参数…但是不行!

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}

这没有添加'WriteBlueLine'方法控制台…我做错了吗?或者要求不可能的事情?


当前回答

我真的不明白人们认为他们能从扩展静态类中得到什么……

仅仅做这样的事情,你会牺牲什么?

public static class MyConsole
{
    public static void WriteBlueLine(string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}

//...

MyConsole.WriteBlueLine("I'm so blue...");
Console.WriteLine("...and I'm not.");

这是最小的额外输入工作,作为奖励,它保持事情透明…

毕竟,即使是常规的扩展方法也只是helper方法的简写。它不允许你对一个类(实例)做任何常规方法做不到的事情。

其他回答

是的,在有限的意义上。

public class DataSet : System.Data.DataSet
{
    public static void SpecialMethod() { }
}

这是可行的,但控制台不能,因为它是静态的。

public static class Console
{       
    public static void WriteLine(String x)
    { System.Console.WriteLine(x); }

    public static void WriteBlueLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.Write(.x);           
    }
}

这是可行的,因为只要它不在同一个名称空间上。问题是您必须为System的每个方法编写一个代理静态方法。控制台。这并不一定是一件坏事,因为你可以添加这样的内容:

    public static void WriteLine(String x)
    { System.Console.WriteLine(x.Replace("Fck","****")); }

or

 public static void WriteLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.WriteLine(x); 
    }

它的工作方式是你将一些东西钩到标准的WriteLine中。它可以是行数或坏词过滤器或其他什么。只要在命名空间中指定Console,就说WebProject1,然后导入命名空间System, WebProject1。控制台将被选择在系统之上。控制台作为命名空间WebProject1中的这些类的默认值。这段代码将会打开所有的控制台。如果你没有指定System.Console.WriteLine,则WriteLine调用为蓝色。

不。扩展方法需要对象的实例变量(值)。但是,您可以围绕ConfigurationManager接口编写一个静态包装器。如果实现包装器,则不需要扩展方法,因为可以直接添加方法。

 public static class ConfigurationManagerWrapper
 {
      public static ConfigurationSection GetSection( string name )
      {
         return ConfigurationManager.GetSection( name );
      }

      .....

      public static ConfigurationSection GetWidgetSection()
      {
          return GetSection( "widgets" );
      }
 }

从c# 7开始,这是不支持的。然而,关于在c# 8中集成这样的东西的讨论和建议值得支持。

这是不可能的。

是的,我认为MS犯了一个错误。

他们的决定没有意义,迫使程序员编写(如上所述)一个毫无意义的包装器类。

下面是一个很好的例子:试图扩展静态MS单元测试类Assert:我想要一个Assert方法AreEqual(x1,x2)。

做到这一点的唯一方法是指向不同的类或围绕100个不同的Assert方法编写包装器。为什么! ?

如果决定允许实例的扩展,我认为没有任何逻辑理由不允许静态扩展。一旦实例可以扩展,关于分段库的争论就站不住脚了。

如果你愿意通过创建静态类的变量并将其赋值为null来“frig”它,你可以这样做。然而,这个方法对类的静态调用是不可用的,所以不确定它会有多少用处:

Console myConsole = null;
myConsole.WriteBlueLine("my blue line");

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}