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


当前回答

您可以使用null类型转换使其工作。

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

扩展:

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

YourType:

public class YourType { }

其他回答

我试着用系统来做这件事。当时我正在学习扩展方法,但没有成功。正如其他人提到的,原因是扩展方法需要类的实例。

你能在c#中为类添加静态扩展吗?不,但你可以这样做:

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

下面是它的工作原理。虽然在技术上不能编写静态扩展方法,但这段代码利用了扩展方法中的漏洞。这个漏洞是你可以在空对象上调用扩展方法而不会得到空异常(除非你通过@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(...)

现在为什么我选择调用默认构造函数作为一个例子,为什么我不只是返回新的T()在第一个代码片段而不做所有的表达式垃圾? 今天是你的幸运日,因为你有一个2。任何高级的。net开发人员都知道,new T()很慢,因为它生成了对System的调用。激活器,它在调用默认构造函数之前使用反射获取默认构造函数。该死的微软! 然而,我的代码直接调用对象的默认构造函数。

静态扩展将比这更好,但紧急时刻需要紧急措施。

不。扩展方法定义需要所扩展类型的实例。这是不幸的;我不知道为什么需要……

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

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

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

如果你愿意通过创建静态类的变量并将其赋值为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();
    }
}