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 queexpr
.
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?
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})
{ … }
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,
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".
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;
}