Can I add extension methods to an existing static class?

前端 未结 15 1746
慢半拍i
慢半拍i 2020-11-22 07:23

I\'m a fan of extension methods in C#, but haven\'t had any success adding an extension method to a static class, such as Console.

For example, if I want to add an e

相关标签:
15条回答
  • 2020-11-22 07:28

    The following was rejected as an edit to tvanfosson's answer. I was asked to contribute it as my own answer. I used his suggestion and finished the implementation of a ConfigurationManager wrapper. In principle I simply filled out the ... in tvanfosson's answer.

    No. Extension methods require an instance of an object. You can however, write a static wrapper around the ConfigurationManager interface. If you implement the wrapper, you don't need an extension method since you can just add the method directly.

    public static class ConfigurationManagerWrapper
    {
        public static NameValueCollection AppSettings
        {
            get { return ConfigurationManager.AppSettings; }
        }
    
        public static ConnectionStringSettingsCollection ConnectionStrings
        {
            get { return ConfigurationManager.ConnectionStrings; }
        }
    
        public static object GetSection(string sectionName)
        {
            return ConfigurationManager.GetSection(sectionName);
        }
    
        public static Configuration OpenExeConfiguration(string exePath)
        {
            return ConfigurationManager.OpenExeConfiguration(exePath);
        }
    
        public static Configuration OpenMachineConfiguration()
        {
            return ConfigurationManager.OpenMachineConfiguration();
        }
    
        public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
        {
            return ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel);
        }
    
        public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap)
        {
            return ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
        }
    
        public static void RefreshSection(string sectionName)
        {
            ConfigurationManager.RefreshSection(sectionName);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:31

    No. Extension methods require an instance variable (value) for an object. You can however, write a static wrapper around the ConfigurationManager interface. If you implement the wrapper, you don't need an extension method since you can just add the method directly.

     public static class ConfigurationManagerWrapper
     {
          public static ConfigurationSection GetSection( string name )
          {
             return ConfigurationManager.GetSection( name );
          }
    
          .....
    
          public static ConfigurationSection GetWidgetSection()
          {
              return GetSection( "widgets" );
          }
     }
    
    0 讨论(0)
  • 2020-11-22 07:36

    As for extension methods, extension methods themselves are static; but they are invoked as if they are instance methods. Since a static class is not instantiable, you would never have an instance of the class to invoke an extension method from. For this reason the compiler does not allow extension methods to be defined for static classes.

    Mr. Obnoxious wrote: "As any advanced .NET developer knows, new T() is slow because it generates a call to System.Activator which uses reflection to get the default constructor before calling it".

    New() is compiled to the IL "newobj" instruction if the type is known at compile time. Newobj takes a constructor for direct invocation. Calls to System.Activator.CreateInstance() compile to the IL "call" instruction to invoke System.Activator.CreateInstance(). New() when used against generic types will result in a call to System.Activator.CreateInstance(). The post by Mr. Obnoxious was unclear on this point... and well, obnoxious.

    This code:

    System.Collections.ArrayList _al = new System.Collections.ArrayList();
    System.Collections.ArrayList _al2 = (System.Collections.ArrayList)System.Activator.CreateInstance(typeof(System.Collections.ArrayList));
    

    produces this IL:

      .locals init ([0] class [mscorlib]System.Collections.ArrayList _al,
               [1] class [mscorlib]System.Collections.ArrayList _al2)
      IL_0001:  newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()
      IL_0006:  stloc.0
      IL_0007:  ldtoken    [mscorlib]System.Collections.ArrayList
      IL_000c:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
      IL_0011:  call       object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type)
      IL_0016:  castclass  [mscorlib]System.Collections.ArrayList
      IL_001b:  stloc.1
    
    0 讨论(0)
  • 2020-11-22 07:39

    yes, in a limited sense.

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

    This works but Console doesn't because it's static.

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

    This works because as long as it's not on the same namespace. The problem is that you have to write a proxy static method for every method that System.Console have. It's not necessarily a bad thing as you can add something like this:

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

    The way it works is that you hook something into the standard WriteLine. It could be a line count or bad word filter or whatever. Whenever you just specify Console in your namespace say WebProject1 and import the namespace System, WebProject1.Console will be chosen over System.Console as default for those classes in namespace WebProject1. So this code will turn all the Console.WriteLine calls into blue insofar as you never specified System.Console.WriteLine.

    0 讨论(0)
  • 2020-11-22 07:40

    You can use a cast on null to make it work.

    public static class YoutTypeExtensionExample
    {
        public static void Example()
        {
            ((YourType)null).ExtensionMethod();
        }
    }
    

    The extension:

    public static class YourTypeExtension
    {
        public static void ExtensionMethod(this YourType x) { }
    }
    

    YourType:

    public class YourType { }
    
    0 讨论(0)
  • 2020-11-22 07:41

    As of C#7 this isn't supported. There are however discussions about integrating something like that in C#8 and proposals worth supporting.

    0 讨论(0)
提交回复
热议问题