Can I add extension methods to an existing static class?

前端 未结 15 1723
慢半拍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:42

    Can you add static extensions to classes in C#? No but you can do this:

    public static class Extensions
    {
        public static T Create<T>(this T @this)
            where T : class, new()
        {
            return Utility<T>.Create();
        }
    }
    
    public static class Utility<T>
        where T : class, new()
    {
        static Utility()
        {
            Create = Expression.Lambda<Func<T>>(Expression.New(typeof(T).GetConstructor(Type.EmptyTypes))).Compile();
        }
        public static Func<T> Create { get; private set; }
    }
    

    Here's how it works. While you can't technically write static extension methods, instead this code exploits a loophole in extension methods. That loophole being that you can call extension methods on null objects without getting the null exception (unless you access anything via @this).

    So here's how you would use this:

        var ds1 = (null as DataSet).Create(); // as oppose to DataSet.Create()
        // or
        DataSet ds2 = null;
        ds2 = ds2.Create();
    
        // using some of the techniques above you could have this:
        (null as Console).WriteBlueLine(...); // as oppose to Console.WriteBlueLine(...)
    

    Now WHY did I pick calling the default constructor as an example, and AND why don't I just return new T() in the first code snippet without doing all of that Expression garbage? Well todays your lucky day because you get a 2fer. 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. Damn you Microsoft! However my code calls the default constructor of the object directly.

    Static extensions would be better than this but desperate times call for desperate measures.

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

    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();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:47

    Its not possible.

    And yes 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.

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