Methodenverkettung in C #

74

Ich habe eigentlich keine Ahnung, wie das in C # heißt. Aber ich möchte meiner Klasse die Funktionalität hinzufügen, um mehrere Elemente gleichzeitig hinzuzufügen.

myObj.AddItem(mItem).AddItem(mItem2).AddItem(mItem3);
Patrick
quelle
stackoverflow.com/a/2055701/5558126 Gibt ein gutes Beispiel für die Implementierung
Vladimir verleg

Antworten:

121

Die von Ihnen erwähnte Technik wird als verkettbare Methode bezeichnet. Es wird häufig beim Erstellen von DSLs oder fließenden Schnittstellen in C # verwendet.

Das typische Muster besteht darin, dass Ihre AddItem () -Methode eine Instanz der Klasse (oder Schnittstelle) zurückgibt, zu der sie gehört. Dadurch können nachfolgende Anrufe daran gekettet werden.

public MyCollection AddItem( MyItem item )
{
   // internal logic...

   return this;
}

Einige Alternativen zur Methodenverkettung zum Hinzufügen von Elementen zu einer Sammlung umfassen:

Verwenden der paramsSyntax, um die Übergabe mehrerer Elemente an Ihre Methode als Array zu ermöglichen. Nützlich, wenn Sie die Array-Erstellung ausblenden und Ihren Methoden eine variable Argumentsyntax bereitstellen möchten:

public void AddItems( params MyItem[] items )
{
    foreach( var item in items )
        m_innerCollection.Add( item );
}

// can be called with any number of arguments...
coll.AddItems( first, second, third );
coll.AddItems( first, second, third, fourth, fifth );

Bereitstellen einer Überladung vom Typ IEnumerable oder IEnumerable, damit mehrere Elemente zusammen an Ihre Sammlungsklasse übergeben werden können.

public void AddItems( IEnumerable<MyClass> items )
{
    foreach( var item in items )
         m_innerCollection.Add( item );
}

Verwenden Sie die .NET 3.5-Auflistungsinitialisierersyntax. Add( item )Ihre Klasse muss eine einzelne Parametermethode bereitstellen, IEnumerable implementieren und einen Standardkonstruktor haben (oder Sie müssen einen bestimmten Konstruktor in der Initialisierungsanweisung aufrufen). Dann können Sie schreiben:

var myColl = new MyCollection { first, second, third, ... };
LBushkin
quelle
1
+1 lernte neue Dinge: D Ich dachte, ich müsste eine andere Methode für die Chaning-Methode machen
GaryNg
33

Verwenden Sie diesen Trick:

public class MyClass
{
    private List<MyItem> _Items = new List<MyItem> ();

    public MyClass AddItem (MyItem item)
    {
        // Add the object
        if (item != null)
            _Items.Add (item)

        return this;
    }
}

Es gibt die aktuelle Instanz zurück, mit der Sie Methodenaufrufe verketten können (wodurch mehrere Objekte "gleichzeitig" hinzugefügt werden.

Nutzer
quelle
Sie müssen das Argument nicht auf AddItem to MyClass beschränken. Könnte wahrscheinlich Objekt oder Gegenstand oder so etwas sein.
Mats Fredriksson
15

"Ich habe eigentlich keine Ahnung, wie das in c # heißt."

Eine fließende API; StringBuilderist das häufigste .NET-Beispiel:

var sb = new StringBuilder();
string s = sb.Append("this").Append(' ').Append("is a ").Append("silly way to")
     .AppendLine("append strings").ToString();
Marc Gravell
quelle
11

Andere haben in Bezug auf die direkte Verkettung von Methoden geantwortet, aber wenn Sie C # 3.0 verwenden, sind Sie möglicherweise an Sammlungsinitialisierern interessiert. Sie sind nur verfügbar, wenn Sie einen Konstruktoraufruf ausführen, und nur, wenn Ihre Methode über geeignete AddMethoden und Implementierungen verfügt IEnumerable, aber dann können Sie tun:

MyClass myClass = new MyClass { item1, item2, item3 };
Jon Skeet
quelle
5

Warum benutzt du das paramsSchlüsselwort nicht?

public void AddItem (params MyClass[] object)
{
    // Add the multiple items
}
bruno conde
quelle
4

Sie können eine Erweiterungsmethode hinzufügen, um dies zu unterstützen, vorausgesetzt, Ihre Klasse erbt von ICollection:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void CanChainStrings()
    {
        ICollection<string> strings = new List<string>();

        strings.AddItem("Another").AddItem("String");

        Assert.AreEqual(2, strings.Count);
    }
}
public static class ChainAdd
{
    public static ICollection<T> AddItem<T>(this ICollection<T> collection, T item)
    {
        collection.Add(item);
        return collection;
    }
}
GC.
quelle
3

Wie wäre es mit

AddItem(ICollection<Item> items);

oder

AddItem(params Item[] items);

Sie können sie so verwenden

myObj.AddItem(new Item[] { item1, item2, item3 });
myObj.AddItem(item1, item2, item3);

Dies ist keine Methodenverkettung, sondern fügt Ihrem Objekt in einem Aufruf mehrere Elemente hinzu.

Martin Liversage
quelle
1

Wenn Ihr Element als Liste fungiert, möchten Sie möglicherweise eine Schnittstelle wie iList oder iEnumerable / iEnumerable implementieren.

Unabhängig davon ist der Schlüssel zum Verketten von Anrufen, wie Sie möchten, die Rückgabe des gewünschten Objekts.

public Class Foo
{
   public Foo AddItem(Foo object)
   {
        //Add object to your collection internally
        return this;
   }
}
Tim Hoolihan
quelle
1

Etwas wie das?

class MyCollection
{
    public MyCollection AddItem(Object item)
    {
        // do stuff
        return this;
    }
}
Mats Fredriksson
quelle