"Dies" im Funktionsparameter


88

Wenn ich mir einige Codebeispiele für HtmlHelpers ansehe, sehe ich Deklarationen, die wie folgt aussehen:

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params )

Ich kann mich nicht erinnern, diese Art von Konstrukt irgendwo anders gesehen zu haben - kann jemand den Zweck des "Dies" erklären? Ich dachte, wenn ich etwas öffentlich statisch deklariere, muss die Klasse nicht instanziiert werden - was ist also "das" in diesem Fall?

Antworten:


210

Dies ist die Syntax zum Deklarieren von Erweiterungsmethoden, eine neue Funktion von C # 3.0.

Eine Erweiterungsmethode ist Teilcode, Teil-Compiler "magic", wobei der Compiler mithilfe von Intellisense in Visual Studio den Eindruck erweckt, dass Ihre Erweiterungsmethode tatsächlich als Instanzmethode für das betreffende Objekt verfügbar ist.

Lassen Sie mich ein Beispiel geben.

Es gibt keine Methode für die String-Klasse mit dem Namen GobbleGobble. Erstellen wir also eine Erweiterungsmethode:

public static class StringExtensions
{
    public static void GobbleGobble(this string s)
    {
        Console.Out.WriteLine("Gobble Gobble, " + s);
    }
}

Der Klassenname ist nur meine Namenskonvention, es ist nicht notwendig, ihn so zu benennen, aber er muss statisch sein, ebenso wie die Methode.

Nachdem Sie die obige Methode deklariert haben, können Sie in Visual Studio Folgendes eingeben:

String s = "Turkey Baster!";
s.

Warten Sie nach dem Punkt auf Intellisense und stellen Sie fest, dass dort eine GobbleGobble-Methode vorhanden ist. Vervollständigen Sie den Code wie folgt:

String s = "Turkey Baster!";
s.GobbleGobble();

Wichtig : Die Klasse, in der die Erweiterungsmethode deklariert ist, muss dem Compiler und dem Intellisense-Prozessor zur Verfügung stehen, damit Intellisense die Methode anzeigen kann. Wenn Sie GobbleGobble manuell eingeben und die Verknüpfung Ctrl+ verwenden ., hilft es Ihnen nicht, mithilfe von Anweisungen in die Datei das Richtige zu finden.

Beachten Sie, dass der Parameter der Methode verschwunden ist. Der Compiler bewegt sich stillschweigend um die wichtigen Bits:

String s = "Turkey Baster!";
s.GobbleGobble();
^     ^
|     +-- the compiler will find this in the StringExtensions class
|
+-- will be used as the first parameter to the method

Somit wird der obige Code vom Compiler folgendermaßen transformiert:

String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);

Zum Zeitpunkt des Anrufs ist also nichts Magisches daran, es ist nur ein Aufruf einer statischen Methode.

Beachten Sie, dass, wenn Ihre Erweiterungsmethode mehr als einen Parameter deklariert, nur der erste den thisModifikator unterstützt und der Rest wie gewohnt als Teil des Methodenaufrufs angegeben werden muss:

public static void GobbleGobble(this string value, string extra)
{                                            |              |
    ...                                      |              |
}                                            |              |
                                             |              |
+--------------------------------------------+              |
|                                                           |
v                                                           |
s.GobbleGobble("extra goes here");                          |
                        ^                                   |
                        |                                   |
                        +-----------------------------------+

Erweiterungsmethoden wurden teilweise aufgrund von Linq hinzugefügt, bei dem die Linq-Syntax von C # nach entsprechend benannten Erweiterungsmethoden für die im Spiel befindlichen Objekte sucht. Dies bedeutet, dass Sie die Linq-Unterstützung in jede Art von Klasse "einführen" können, indem Sie einfach die richtige Erweiterung deklarieren Methoden. Natürlich ist die vollständige Unterstützung von Linq eine Menge Arbeit, aber es ist möglich.

Außerdem sind Erweiterungsmethoden für sich genommen sehr nützlich. Lesen Sie sie daher nach.

Hier sind ein paar Links:


6
Ich werde definitiv anfangen, den Begriff "Gobble Gobble Magic" zu verwenden.
Chris

Youtube hat den Link erneut unterbrochen , youtube.com/watch?v=Bz_heb9Rz2g , immer noch um @ 1: 00 und weiter.
Lasse V. Karlsen

8

Nach Erweiterungsmethoden habe ich sie wie verrückt benutzt. Hier sind einige, die ich ständig benutze.

public static T ChangeType<T>(this object obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

Funktioniert so ..

int i = "123".ChangeType<int>();
bool valid = "bool".ChangeType<bool>();
int id = dataSet.Tables[0].Rows[0]["Id"].ChangeType<int>();

Ja, es wird auf jedem einzelnen Objekt angezeigt, kann ärgerlich sein, aber da ich dies für so ziemlich jeden Datentyp verwende, hilft es, es einfach an ein Objekt anzuhängen, anstatt es für jeden möglichen Datentyp zu duplizieren.

public static string ToXml(this object serializableObject)
{
    var aMemStr = new MemoryStream();
    try
    {
        var serializer = new XmlSerializer(serializableObject.GetType());
        serializer.Serialize(new XmlTextWriter(aMemStr, null), serializableObject);
        return Encoding.UTF8.GetString(aMemStr.ToArray());
    }
    finally { if (aMemStr != null) { aMemStr.Dispose(); } }
}

string xml = dataSet.ToXml();

public static T ToObject<T>(this string xmlString)
{
    var aStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString));
    try { return (T)new XmlSerializer(typeof(T)).Deserialize(aStream); }
    finally { if (aStream != null) { aStream.Dispose(); aStream = null; } }
}

DataSet dataSet = xml.ToObject<DataSet>();

6

Es wird für Erweiterungsmethoden verwendet. Grundsätzlich "kleben" Sie den Helpernamen auf das htmlHelper-Objekt, damit Sie sagen können:

new HtmlHelper().HelperName(...more regular params);

4

Das wäre eine Erweiterungsmethode. Mit ihnen können Sie eine Klasse über statische Methoden "erweitern", die außerhalb der ursprünglichen Klasse liegen.

Angenommen, Sie haben eine hilfreiche Zeichenfolgenmethode, die Sie ständig verwenden ...

public int CountAllAs(string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}

Und du nennst es ...

string allAs = "aaaA";
int count = CountAllAs(allAs);

Das ist nicht so schlecht. Aber mit einer kleinen Änderung könnten Sie es zu einer Erweiterungsmethode machen, und der Aufruf wäre etwas hübscher:

public static int CountAllAs(this string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}

Und dann nenn es ...

string allAs = "aaaA";
int count = allAs.CountAllAs();

3

Erweiterungsmethoden ...

... sind eine fantastische Möglichkeit, Funktionen einzuschließen, beispielsweise wenn Sie das Dekorationsmuster verwenden , ohne jedoch den gesamten Code neu zu gestalten oder einen anderen Namen eines gemeinsamen Typs zu verwenden.

public static class Extensions
{
     public static string RemoveComma(this string value)
     {
         if (value == null) throw new ArgumentNullException("value");
        return value.Replace(",", "");
    }
}  

Sie können diesen Code also überall in Ihrer App verwenden.

Console.WriteLine(“Hello, My, Friend”.RemoveComma())

>> Hello My Friend

Das Befehlsattribut this bedeutet also den Typ, zu dem die Erweiterung „hinzugefügt“ wird, und lässt Sie mit dem Wert arbeiten, als ob er als Parameter übergeben worden wäre.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.