web-dev-qa-db-fra.com

Quel est l'avantage des modèles var en C # 7?

Je ne comprends pas le cas d'utilisation des modèles var en C # 7. MSDN :

Une correspondance de modèle avec le modèle var réussit toujours. Sa syntaxe est

expr is var varname

où la valeur de expr est toujours affectée à une variable locale nommée varname. varname est une variable statique du même type que expr.

L'exemple sur MSDN est plutôt inutile à mon avis, notamment parce que la variable if est redondante:

object[] items = { new Book("The Tempest"), new Person("John") };
foreach (var item in items) {
  if (item is var obj)
    Console.WriteLine($"Type: {obj.GetType().Name}, Value: {obj}"); 
}

Ici, je ne vois aucun avantage, vous pourriez avoir le même résultat si vous accédez directement à la variable de boucle item qui est également du type Object. La if est également source de confusion car elle n'est jamais false

Je pourrais utiliser var otherItem = item ou item diectly. Quelqu'un peut-il expliquer le cas d'utilisation mieux?

28
Rango

Le modèle var a été très fréquemment abordé dans le répertoire référentiel de langage C # , étant donné que son cas d'utilisation n'est pas parfaitement clair et que is var x n'effectue pas de contrôle null alors que is T x le fait, ce qui le fait apparaître plutôt inutile.

Cependant, il n’est en réalité pas destiné à être utilisé comme obj is var x. Il est destiné à être utilisé lorsque le côté gauche est pas une variable en soi.

Voici quelques exemples de la spécification . Ils utilisent tous des fonctionnalités qui ne sont pas encore dans C # yet, mais cela montre simplement que l’introduction du modèle var a été faite principalement en préparation de ces choses, de sorte qu’ils n’auront plus à le toucher plus tard.

L'exemple suivant déclare une fonction Deriv pour construire la dérivée d'une fonction à l'aide d'une correspondance de modèle structurel sur un arbre d'expression:

Expr Deriv(Expr e)
{
    switch (e) {
        // …
        case Const(_): return Const(0);
        case Add(var Left, var Right):
            return Add(Deriv(Left), Deriv(Right));
        // …
}

Ici, le modèle var peut être utilisé à l'intérieur des structures pour «extraire» des éléments de la structure. De même, l'exemple suivant simplifie une expression:

Expr Simplify(Expr e)
{
    switch (e) {
        case Mult(Const(0), _): return Const(0);
        // …
        case Add(Const(0), var x): return Simplify(x);
    }
}

Comme gafter écrit ici , l’idée est aussi d’avoir une correspondance de modèle de propriété, permettant ainsi:

if (o is Point {X is 3, Y is var y})
{ … }
15
poke

Sans vérifier les notes de conception sur Github, j'imagine que cela a été ajouté davantage pour des raisons de cohérence avec switch et comme point de départ pour les cas de correspondance de modèle plus avancés, 

De l’original Nouveautés de C # 7.0 post:

Modèles Var de la forme var x (où x est un identifiant), qui correspondent toujours et placent simplement la valeur de l'entrée dans une nouvelle variable x du même type que l'entrée.

Et la récente dissection post par Sergey Teplyakov:

si vous savez exactement ce qui se passe, vous trouverez peut-être ce modèle utile. Il peut être utilisé pour introduire une variable temporaire dans l'expression: Ce modèle crée essentiellement une variable temporaire en utilisant le type réel de l'objet. 

public void VarPattern(IEnumerable<string> s)
{
    if (s.FirstOrDefault(o => o != null) is var v
        && int.TryParse(v, out var n))
    {
        Console.WriteLine(n);
    }
}

L'avertissement juste avant cet extrait est également important: 

Il n’est pas clair pourquoi le comportement est différent dans le mode Release uniquement. Mais je pense que tous les problèmes tombent dans le même panier: la mise en œuvre initiale de la fonctionnalité est sous-optimale. Mais sur la base de ce commentaire de Neal Gafter, cela va changer: "Le code d'abaissement correspondant au modèle est en train d'être réécrit à partir de zéro (afin de prendre en charge les modèles récursifs également). "dans le nouveau code. Mais il faudra un certain temps avant que la réécriture soit prête pour le prime time.".

Selon Christian Nagel :

L’avantage est que la variable déclarée avec le mot clé var est du type réel de l’objet, 

14
Panagiotis Kanavos

La seule chose à laquelle je peux penser immédiatement, c'est si vous constatez que vous avez écrit deux blocs de code identiques (en un seul switch), un pour expr is object a et l'autre pour expr is null.

Vous pouvez combiner les blocs en basculant sur expr is var a.

Cela peut également être utile dans les scénarios de génération de code où, pour une raison quelconque, vous vous êtes déjà inscrit dans un coin et vous attendez toujours à générer une correspondance de modèle, mais souhaitez maintenant émettre un modèle "correspondre à tout".

1
Damien_The_Unbeliever

Dans la plupart des cas, il est vrai que l’avantage du modèle var n’est pas clair et peut même être une mauvaise idée. Cependant, comme moyen de capturer des types anonymes dans une variable temporaire, cela fonctionne très bien . Nous espérons que cet exemple illustre bien ce qui suit:.

        var sample = new(int id, string name, int age)[] { 
                                                          (1, "jonas", 50),                                                                                                                            
                                                          (2, "frank", 48) };

        var f48 = from s in sample 
                  where s.age == 48 
                  select new { Name = s.name, Age = s.age };

        switch(f48.FirstOrDefault())
        {
            case var choosen when choosen.Name == "frank":
                WriteLine(choosen.Age);
                break;
            case null:
                WriteLine("not found");
                break;
        }
0
Jonas Brandel