2010-11-24 3 views
10

Oft möchten Sie mehrere Werte senden, aber aufgrund der geringen Verwendung (d. H. Es wird nur an ein oder zwei Stellen verwendet), ist es schwer zu rechtfertigen, einen neuen Typ zu erstellen. Die Tuple<...> und KeyValuePair<,> Art sind sehr nützlich, aber es gibt keine echte Sprachunterstützung für sie.Gibt es Tipps, um das Arbeiten mit Tupel in C# zu erleichtern?

Nun, ein guter Trick für Listen von Tupeln ist es, einen Typ zu erstellen, der die Liste erweitert und eine benutzerdefinierte Add-Methode hinzufügt: z.

public class TupleList<T1,T2> : List<Tuple<T1,T2>>{ 
    public void Add(T1 key, T2 value){ 
     base.Add(Tuple.Create(key, value)); 
    } 
} 

Das bedeutet, dass, wenn ich eine Methode, die eine IEnumerable<Tuple<int,string>> nimmt, habe ich den folgenden Code schnell die Liste aufbauen verwenden können, um wie so ::

Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}}); 

Dies macht Werte in ein Tupel Wicklung Liste einfacher, da wir nicht ständig Tuple.Create sagen müssen, und uns fast zu einer netten funktionalen Sprachensyntax bringt.

Wenn Sie jedoch mit einem Tupel arbeiten, ist es nützlich, es in seine verschiedenen Komponenten zu zerlegen. Diese Erweiterungsmethode könnte nützlich sein, in dieser Hinsicht ::

public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2) 
    { 
     var1 = tuple.Item1; 
     var2 = tuple.Item2; 
    } 

Aber auch das ist ärgerlich, da out-Parameter überhaupt nicht Variante sind. Das heißt, wenn T1 eine Zeichenkette ist, kann ich keine Objektvariable einsenden, obwohl sie zuweisbar ist, wenn ich die Abwicklung ansonsten von Hand erledigen kann. Ich kann nicht wirklich einen Grund vorschlagen, warum Sie diese Abweichung wollen, aber wenn es dort ist, kann ich nicht sehen, warum Sie es verlieren möchten.

Hat jemand andere Tipps, um in C# funktionierende Tupel oder tupelartige Objekte einfacher zu machen?

Eine wichtige potenzielle Verwendung für Tupel könnte generische Memoisierung sein. Das ist sehr einfach in Sprachen wie F #, aber schwer in C#.

Ich verwende derzeit Tuples, um eine MethodBase und ein Array von Token (Konstanten, Objekte oder Argumenttoken) bereitzustellen, die einem dynamisch erstellten Objekt zur Verfügung gestellt werden, um bestimmte Elementfelder zu erstellen.

Da ich die Syntax für API-Konsumenten einfacher machen wollte, habe ich Add-Methoden erstellt, die ein ConstructorInfo oder ein MethodInfo und ein params Array von Objekten übernehmen können.

Edit: Eric Lippert wie üblich eine hervorragende Motivation für hier Tupeln mit und er sagt auch, was ich vermutete es wirklich keine Unterstützung ist: What requirement was the tuple designed to solve?

+0

Können Sie uns Ihren Anwendungsfall zeigen, in dem Sie es vorziehen, Parameter des Typs 'Objekt' anstelle von Variablen einzugeben, die tatsächlich eingegeben wurden? Zeigen Sie uns, wie Sie mit ein bisschen Kontext "Abwickeln" nennen möchten. –

+1

out-Parameter sind starr, weshalb sie nicht als die Wahl zur Wahl vorgeschlagen werden. Ich würde für API-Unterstützung wie F # töten, die Parameter in Tupel ausgibt. –

+0

Komposition über Vererbung! – Eric

Antwort

4

Verwenden Mono! Sie haben experimentelle Unterstützung für binding variables to tuple members so können Sie wie eine Methode aufrufen

Tuple<string, string, string, int, string> ParseUri (string url); 

mit Code wie

(user, password, host, port, path) = ParseUri (url); 
+13

Das ist ein ziemlich schlechter Rat. Sicher, diese Funktion ist ordentlich, aber "Use Mono" ist keine Entscheidung, die viele Leute treffen können. –

+6

Das sieht wirklich gut aus, leider kann ich für die Arbeit nicht ändern, für welche Laufzeit wir kompilieren. –

+0

+ experimentelle Unterstützung – Eric

5

In C# können Sie alias generische Typen geschlossen, die Tuple ist, dies ermöglicht es Ihnen, einige besser bieten Einblick in das, was beabsichtigt ist. Ändert den Code nicht viel, aber wenn Sie sich das Beispiel ansehen, ist die Absicht von GetTemp besser.

Ohne Alias:

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var result = GetTemp(10, 10); 
      Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1); 
     } 

     // You give a lat & a long and you get the closest city & temp for it 
     static Tuple<double, string> GetTemp(double lat, double @long) 
     { 
      // just for example 
      return Tuple.Create(10d, "Mordor"); 
     }   
    } 
} 

Mit Alias:

namespace ConsoleApplication1 
{ 
    using CityTemp = Tuple<double, string>; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var result = GetTemp(10, 10); 
      Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1); 
     } 

     // You give a lat & a long and you get the closest city & temp for it 
     static CityTemp GetTemp(double lat, double @long) 
     { 
      // just for example    
      return new CityTemp(10, "Mordor"); 
     } 
    } 
} 
2

Es wird eine geile Tupel-Funktion mit C# kommenden seinem 7/Visual Studio 15.

im Grunde kann man soething tun wie das

static (int x, int y) DoSomething() 
{ 
    return (1, 2); 
} 

static void Test() 
{ 
    var cool = DoSomething(); 
    var value = cool.x; 
} 

Lesen Sie nach post

Verwandte Themen