views:

3670

answers:

9

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 extension to Console, called 'WriteBlueLine', so that I can go:

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

I tried this by adding a local, public static method, with Console as a 'this' parameter... but no dice!

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

This didn't add a 'WriteBlueLine' method to Console... am I doing it wrong? Or asking for the impossible?

+19  A: 

You are indeed asking the impossible.

Justice
@Justice: I wouldn't say it's *impossible*, I also think it would be a good idea! As I have came across various situations where the ability to extend a .NET static class would be ideal.
James
I'm sure loads of people have arrived at this stackoverflow post for the same very reason. I'm currently trying to extend the System.Web.Security.Roles static class to pull back custom sub roles from a database.
Brian Scott
+4  A: 

You can't add static methods to a type. You can only add (pseudo-)instance methods to an instance of a type.

The point of the this modifier is to tell the C# compiler to pass the instance on the left-side of the . as the first parameter of the static/extension method.

In the case of adding static methods to a type, there is no instance to pass for the first parameter.

Brannon
+4  A: 

You may be asking the impossible as it stands, however this is certainly something that would be as technically possible to do as instance-based extension methods if they provided a syntax for it. Sounds like the idea simply got missed by the C# architects. Maybe something similar to partial classes that could package extension methods for a class (without actually changing the class itself):

// NOTE: this is an imaginary (not valid) syntax!
public extension class Console
{
    public static void WriteBlueLine( string text)
    {
        // ...
    }
}

This might also have been a somewhat cleaner (others' opinions might well differ on this) way to package instance-based extension methods as well. There would be namespacing issues, but with some thought (which I clearly have not done much of on this) I think they could be worked out.

Unfortunately, you came up with the idea too late!

Michael Burr
Wow Mike -- i like that you're using your imagination here. Extension classes FTW!
Leon Bambrick
+1  A: 

I tried to do this with System.Environment back when I was learning extension methods and was not successful. The reason is, as others mention, because extension methods require an instance of the class.

Robert S.
+4  A: 

Nope. Extension method definitions require an instance of the type you're extending. Its unfortunate; I'm not sure why its required...

Will
It is because an extension method is used to extend an instance of an object. If they didn't do that they would just be regular static methods.
Derek Ekins
It'd be nice to do both, wouldn't it?
Will
+23  A: 

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 ConfigurationSection GetSection( string name )
      {
         return ConfigurationManager.GetSection( name );
      }

      .....

      public static ConfigurationSection GetWidgetSection()
      {
          return GetSection( "widgets" );
      }
 }
tvanfosson
I didn't understand this example. Any help?
Luis Filipe
@Luis -- in context, the idea would be "could I add an extension method to the ConfigurationManager class to get a specific section?" You can't add an extension method to a static class since it requires an instance of the object, but you can write a wrapper class (or facade) that implements the same signature and defers the actual call to the real ConfigurationManager. You can add whatever method you want to the wrapper class so it doesn't need to be an extension.
tvanfosson
@tvanfosson: thanks a lot
Luis Filipe
I find it more helpful to just add a static method to the class implementing ConfigurationSection. So given an implementation called MyConfigurationSection, I would call MyConfigurationSection.GetSection(), which returns the section already typed, or null if it does not exist. End result is the same, but it avoids adding a class.
tap
@tap - it's only an example, and the first one that came to mind. The single responsibility principle comes into play, though. Should the "container" actually be responsible for interpreting itself from the configuration file? Normally I simply have ConfigurationSectionHandler and cast the output from ConfigurationManager to the appropriate class and don't bother with the wrapper.
tvanfosson
+2  A: 

Yea I think MS made a mistake here.

Their decision does not make sense and forces programmers to write (as described above) a pointless wrapper class.

Here is a good example: Trying to extend static MS Unit testing class Assert: I want 1 more Assert method AreEqual(x1,x2).

The only way to do this is to point to different classes or write a wrapper around 100s of different Assert methods. Why!?

If the decision was been made to allow extensions of instances I see no logical reason to not allow static extensions. The arguments about sectioning libraries does not stand up once instances can be extended.

Tom Deloford
+2  A: 

Maybe you could add a static class with your custom namespace and the same class name:

using CLRConsole = System.Console;

namespace ExtensionMethodsDemo
{
    public static class Console
    {
        public static void WriteLine(string value)
        {
            CLRConsole.WriteLine(value);
        }

        public static void WriteBlueLine(string value)
        {
            System.ConsoleColor currentColor = CLRConsole.ForegroundColor;

            CLRConsole.ForegroundColor = System.ConsoleColor.Blue;
            CLRConsole.WriteLine(value);

            CLRConsole.ForegroundColor = currentColor;
        }

        public static System.ConsoleKeyInfo ReadKey(bool intercept)
        {
            return CLRConsole.ReadKey(intercept);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteBlueLine("This text is blue");   
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey(true);
        }
    }
}
Pag Sun
+1  A: 

You CAN do this if you are willing to "frig" it a little by making a variable of the static class and assigning it to null. However, this method would not be available to static calls on the class, so not sure how much use it would be:

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();
    }
}
Tenaka
this is exactly what I did. My class is called MyTrace :)
Gishu