648 Stimmen

Kann ich einer bestehenden statischen Klasse Erweiterungsmethoden hinzufügen?

Ich bin ein Fan von Erweiterungsmethoden in C#, hatte aber noch keinen Erfolg beim Hinzufügen einer Erweiterungsmethode zu einer statischen Klasse, wie z. B. Console .

Wenn ich zum Beispiel eine Erweiterung hinzufügen möchte zu Console mit der Bezeichnung WriteBlueLine ', damit ich gehen kann:

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

Ich habe dies versucht, indem ich eine lokale, öffentliche statische Methode hinzugefügt habe, mit Console als ' this ' Parameter... aber keine Chance!

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

Dies fügte kein ' WriteBlueLine ' Methode zu Console ... mache ich es falsch? Oder verlange ich etwas Unmögliches?

3 Stimmen

O

0 Stimmen

I

14 Stimmen

T p , E .

333voto

tvanfosson Punkte 506878

Nein. Erweiterungsmethoden erfordern eine Instanzvariable (Wert) für ein Objekt. Sie können jedoch einen statischen Wrapper um die Methode ConfigurationManager Schnittstelle. Wenn Sie den Wrapper implementieren, benötigen Sie keine Erweiterungsmethode, da Sie die Methode einfach direkt hinzufügen können.

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

      .....

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

98voto

Mr. Obnoxious Punkte 987

Können Sie statische Erweiterungen zu Klassen in C# hinzufügen? Nein, aber Sie können dies tun:

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

Und so funktioniert es. Während man technisch gesehen keine statischen Erweiterungsmethoden schreiben kann, nutzt dieser Code stattdessen eine Lücke in den Erweiterungsmethoden aus. Dieses Schlupfloch besteht darin, dass Sie Erweiterungsmethoden für Null-Objekte aufrufen können, ohne die Null-Ausnahme zu erhalten (es sei denn, Sie greifen über @this auf etwas zu).

So würden Sie dies also verwenden:

    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(...)

Warum habe ich nun den Aufruf des Standardkonstruktors als Beispiel gewählt, und warum gebe ich im ersten Codeschnipsel nicht einfach new T() zurück, ohne den ganzen Expression-Müll zu machen? Nun, heute ist Ihr Glückstag, denn Sie bekommen einen 2fer. Wie jeder fortgeschrittene .NET-Entwickler weiß, ist new T() langsam, weil es einen Aufruf an System.Activator generiert, der Reflection verwendet, um den Standardkonstruktor zu erhalten, bevor er ihn aufruft. Verdammt seist du Microsoft! Mein Code ruft jedoch den Standardkonstruktor des Objekts direkt auf.

Statische Verlängerungen wären besser als diese, aber verzweifelte Zeiten erfordern verzweifelte Maßnahmen.

80voto

Tom Deloford Punkte 1877

Das ist nicht möglich.

Und ja, ich denke, MS hat hier einen Fehler gemacht.

Diese Entscheidung ist nicht sinnvoll und zwingt die Programmierer dazu, (wie oben beschrieben) eine sinnlose Wrapper-Klasse zu schreiben.

Hier ist ein gutes Beispiel: Ich versuche, die statische MS-Unit-Testing-Klasse Assert zu erweitern: Ich möchte 1 weitere Assert-Methode AreEqual(x1,x2) .

Die einzige Möglichkeit, dies zu tun, besteht darin, auf verschiedene Klassen zu verweisen oder einen Wrapper für 100 verschiedene Assert-Methoden zu schreiben. Warum?

Wenn die Entscheidung getroffen wurde, Erweiterungen von Instanzen zuzulassen, sehe ich keinen logischen Grund, statische Erweiterungen nicht zuzulassen. Die Argumente zur Aufteilung von Bibliotheken sind nicht mehr stichhaltig, wenn Instanzen erweitert werden können.

38voto

Adel G.Eibesh Punkte 451

Ich bin auf diesen Thread gestoßen, als ich versuchte, eine Antwort auf die gleiche Frage zu finden, die der Auftraggeber hatte. Ich habe nicht die Antwort gefunden, die ich wollte, aber ich endete damit, dies zu tun.

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

Und ich verwende es so:

ConsoleColor.Cyan.WriteLine("voilà");

24voto

mbx Punkte 5915

Ab C#7 wird dies nicht mehr unterstützt. Es gibt jedoch Diskussionen über die Integration von so etwas in C#8 y Unterstützenswerte Vorschläge .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X