我是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'方法控制台…我做错了吗?或者要求不可能的事情?


当前回答

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

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

      .....

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

其他回答

虽然Console的方法是静态的,但它的静态方法Write()和WriteLine()只是分别将调用重定向到Console. out .Write()和Console. out .WriteLine()。Out是一个实例,其类型派生自抽象类TextWriter。这使得为TextWriter定义扩展方法成为可能:

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

    public static void WriteUppercase(this TextWriter writer, string text)
    {
        writer.Write(text.ToUpper());
    }
}

然后可以像这样调用该方法:

Console.Out.WriteBlueLine();

最好的部分是标准错误流实例Console的类型。错误也源于TextWriter,这使得相同的扩展方法也可用于控制台。错误:

Console.Error.WriteBlueLine();

如果您已经定义了像WriteTable()这样的扩展方法(用于将表写入控制台),那么这可能非常有用,因为您还可以将它用于错误流或TextWriter的任何其他对象。

新版本的c#甚至可以用using static语句来获得控制台的红色。前缀:

using static System.Console;

Out.WriteBlueLine("A blue line");
Error.WriteBlueLine("A blue line");

不能向类型添加静态方法。只能向某个类型的实例添加(伪)实例方法。

this修饰符的作用是告诉c#编译器将实例传递到。作为静态/扩展方法的第一个参数。

在向类型添加静态方法的情况下,没有为第一个参数传递实例。

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

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

      .....

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

不幸的是,你不能扩展静态类

https://onecompiler.com/csharp/3xvbe7axg

using System;

namespace HelloWorld
{
  public static class console_extensions {
    public static void EXTENSION(this object item) {
      System.Console.WriteLine("HELLO THERE!");
    }
  }
  
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            Console.EXTENSION();
            ((Console)null).EXTENSION();
            Console l = new Console();
            l.EXTENSION();
        }
    }
}

输出

Compilation failed: 4 error(s), 0 warnings

HelloWorld.cs(16,12): error CS0117: `System.Console' does not contain a definition for `EXTENSION'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(17,5): error CS0716: Cannot convert to static type `System.Console'
HelloWorld.cs(18,4): error CS0723: `l': cannot declare variables of static types
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(18,16): error CS0712: Cannot create an instance of the static class `System.Console'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)

但是你可以将null传递给扩展方法

using System;

namespace HelloWorld
{
  public static class static_extensions {
      public static void print(this object item, int data = 0) {
      Console.WriteLine("EXT: I AM A STATIC EXTENSION!");
      Console.WriteLine("EXT: MY ITEM IS: " + item);
      Console.WriteLine("EXT: MY DATA IS: " + data);
      string i;
      if (item == null) {
        i = "null";
      } else {
        i = item.GetType().Name;
      }
      Console.WriteLine("EXT: MY TYPE IS: " + i + "\n");
    }
  }

    public class Program
    {
    
        public static void Main(string[] args)
        {
          // an extension method can be
          //   called directly
          //  (null is an instance)
          static_extensions.print(null);

          // an extension method can also be
          //   called directly with arguments
          //  (null is an instance)
          static_extensions.print(null, 1);
          
          // an extension method can also be
          //   called as part of an instance
          int x = 0; // initialize int
          x.print();
          
          // an extension method can also be
          //   called as part of an instance
          //   and with data
          int x2 = 0; // initialize int
          x2.print(2);
          
          // an extension method can also be
          //   called directly from null
          //   since `null` is an instance
          ((string)null).print();
          
          // an extension method can also be
          //   called directly from null
          //   and with data
          //   since `null` is an instance
          ((string)null).print(4);
        }
    }
}

实例:https://onecompiler.com/csharp/3xvbc8s6w

输出:

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 
EXT: MY DATA IS: 1
EXT: MY TYPE IS: null

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 0
EXT: MY TYPE IS: Int32

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 2
EXT: MY TYPE IS: Int32

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null

EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 
EXT: MY DATA IS: 4
EXT: MY TYPE IS: null

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

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

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方法的简写。它不允许你对一个类(实例)做任何常规方法做不到的事情。