306 votes

Meilleur nommage dans les classes Tuple que "Item1", "Item2".

Existe-t-il un moyen d'utiliser une classe Tuple, mais de fournir les noms des éléments qu'elle contient ?

Par exemple :

public Tuple<int, int, int int> GetOrderRelatedIds()

Cela renvoie les identifiants de OrderGroupId, OrderTypeId, OrderSubTypeId et OrderRequirementId.

Il serait bon que les utilisateurs de ma méthode sachent ce qu'il en est. (Lorsque vous appelez la méthode, les résultats sont result.Item1, result.Item2, result.Item3, result.Item4. Il n'est pas clair de savoir lequel est lequel).

(Je sais que je pourrais simplement créer une classe pour contenir tous ces Ids, mais ces Ids ont déjà leurs propres classes dans lesquelles ils vivent et faire une classe pour la valeur de retour de cette seule méthode semble idiot).

14voto

George Duckett Points 17305

Avec .net 4, vous pourriez peut-être examiner le module ExpandoObject Cependant, ne l'utilisez pas dans ce cas simple car ce qui aurait été des erreurs de compilation devient des erreurs d'exécution.

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.

Un autre élément mérite d'être mentionné : une type anonyme pour l'intérieur d'une méthode mais vous devez créer une classe si vous voulez la renvoyer.

var MyStuff = new
    {
        PropertyName1 = 10,
        PropertyName2 = "string data",
        PropertyName3 = new ComplexType()
    };

6voto

Mihir Dave Points 2341

MichaelMocko La réponse est géniale,

mais je veux ajouter quelques éléments que j'ai dû comprendre

(string first, string middle, string last) LookupName(long id)

La ligne ci-dessus vous donnera erreur de compilation si vous utilisez .net framework < 4.7

Donc si vous avez un projet qui utilise .net framework < 4.7 et que vous voulez toujours utiliser ValueTuple que workAround serait installer este Paquet NuGet

Mise à jour :

Exemple de retour d'un tuple nommé à partir d'une méthode et de son utilisation

public static (string extension, string fileName) GetFile()
{
    return ("png", "test");
}

L'utiliser

var (extension, fileName) = GetFile();

Console.WriteLine(extension);
Console.WriteLine(fileName);

5voto

Qudus Points 22

A partir d'aujourd'hui, c'est aussi simple que ça. Au lieu d'utiliser le mot-clé Tuple

public Tuple<int, int, int int> GetOrderRelatedIds()

Utilisez ça.

public (int alpha, int beta, int candor) GetOrderRelatedIds()

Obtenez les valeurs comme ceci.

var a = GetOrderRelatedIds();
var c = a.alpha;

4voto

Eugene Kulabuhov Points 126

Juste pour ajouter à la réponse de @MichaelMocko. Les Tuples ont quelques problèmes pour le moment :

Vous ne pouvez pas les utiliser dans les arbres d'expression EF.

Ejemplo:

public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        // Selecting as Tuple
        .Select(person => (person.Name, person.Surname))
        .First();
}

La compilation échouera avec l'erreur "An expression tree may not contain a tuple literal". Malheureusement, l'API des arbres d'expression n'a pas été développée pour prendre en charge les tuples lorsque ceux-ci ont été ajoutés au langage.

Suivez (et upvotez) cette question pour les mises à jour : https://github.com/dotnet/roslyn/issues/12897

Pour contourner le problème, vous pouvez d'abord le convertir en type anonyme, puis convertir la valeur en tuple :

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => new { person.Name, person.Surname })
        .ToList()
        .Select(person => (person.Name, person.Surname))
        .First();
}

Une autre option consiste à utiliser ValueTuple.Create :

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname))
        .First();
}

Références :

Vous ne pouvez pas les déconstruire en lambdas.

Il y a une proposition pour ajouter le support : https://github.com/dotnet/csharplang/issues/258

Ejemplo:

public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname));
}

// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })

// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })

Références :

Ils ne sérialisent pas bien

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main() {
        var me = (age: 21, favoriteFood: "Custard");
        string json = JsonConvert.SerializeObject(me);

        // Will output {"Item1":21,"Item2":"Custard"}
        Console.WriteLine(json); 
    }
}

Les noms de champs de tuple ne sont disponibles qu'au moment de la compilation et sont complètement effacés au moment de l'exécution.

Références :

3voto

Joe Mancuso Points 1293

Non, vous ne pouvez pas nommer les membres du tuple.

La solution intermédiaire serait d'utiliser ExpandoObject au lieu de Tuple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X