204 votes

Quelle est la différence entre dynamique (C# 4) et var?

J'avais lu un tas d'articles sur ce nouveau mot-clé qui est expédié avec C# v4, mais je ne pouvais pas faire la différence entre "dynamique" et "var".

Cet article m'a fait réfléchir, mais je ne vois toujours aucune différence.

Est-ce que vous pouvez utiliser "var" seulement comme variable locale, mais dynamique à la fois locale et globale?

Pourriez-vous montrer du code sans mot-clé dynamique puis montrer le même code avec le mot-clé dynamique?

463voto

Marc Gravell Points 482669

var est typé statiquement - le compilateur et le runtime connaissent le type - ils vous permettent juste de taper moins... les deux exemples suivants sont à 100% identiques :

var s = "abc";
Console.WriteLine(s.Length);

et

string s = "abc";
Console.WriteLine(s.Length);

Tout ce qui s'est passé, c'est que le compilateur a déduit que s devait être une chaîne de caractères (à partir de l'initialisation). Dans les deux cas, il sait (dans le code IL) que s.Length signifie la propriété (instance) string.Length.

dynamic est une bête très différente ; il est similaire à object, mais avec une distribution dynamique :

dynamic s = "abc";
Console.WriteLine(s.Length);

Ici, s est typé comme dynamique. Il ne sait rien sur string.Length, car il ne sait rien sur s au moment de la compilation. Par exemple, le code suivant compilerait (mais ne s'exécuterait pas) aussi :

dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);

À l'exécution (seulement), il vérifierait la propriété FlibbleBananaSnowball

Avec dynamic, les propriétés / méthodes / opérateurs / etc sont résolus à l'exécution, en fonction de l'objet réel. Très utile pour parler à COM (qui peut avoir des propriétés uniquement à l'exécution), le DLR, ou d'autres systèmes dynamiques, comme javascript.

3 votes

Une question intéressante serait de savoir s'il existe des ancêtres dynamiques de classes déclarées statiquement. Exemple: class X { public int Y {get;set;} } dynamic(X) s = GetSpecialX(); Appeler string test = s.Y; générerait une erreur de compilation car le compilateur connaît Y, mais string test2 = s.Z compilerait correctement et serait vérifié au moment de l'exécution. Je pourrais penser à beaucoup de valeur de telles classes demi-dynamiques!

0 votes

@rstevens - À ma connaissance, vous pouvez ajouter un comportement dynamique via une interface (même s'il n'y a pas de support direct du langage pour implémenter des types dynamiques en C# - seulement les consommer), donc ce n'est pas irréaliste... oh le plaisir que nous pourrions avoir ;-p

0 votes

Bien qu'il soit important de noter que parfois var peut inférer des types qui ne sont peut-être pas souhaités en raison des sous-types et des conversions implicites. C'est-à-dire que var peut avoir résolu un type statiquement différent de celui attendu lorsque des conversions implicites se produisent (notamment vers un type plus général, mais ce n'est pas limité à cela). Un exemple trivial est object x = "" vs. var x = "" vs. var x = "" as object, mais d'autres cas plus sournois (et réalistes) peuvent se produire et peuvent causer des bugs subtils.

58voto

HVS Points 1219

Les variables déclarées avec var sont implicitement mais statiquement typées. Les variables déclarées avec dynamic sont dynamiquement typées. Cette capacité a été ajoutée au CLR afin de supporter les langages dynamiques comme Ruby et Python.

Je devrais ajouter que cela signifie que les déclarations dynamic sont résolues à l'exécution, tandis que les déclarations var sont résolues à la compilation.

42voto

Suneel Gupta Points 109

Je vais expliquer la différence entre dynamique et var.

dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";

Cela fonctionnera. Le compilateur peut recréer le type de variable dynamique.
d'abord, il crée le type comme entier et après cela, le compilateur recréera le type comme chaîne de caractères
mais en cas de var

var v1;  // Le compilateur va générer une erreur car nous devons initialiser au moment de la déclaration  
var v2 = 1; // Le compilateur va créer v1 comme **entier**
v2 = "Suneel Gupta"; // Le compilateur va générer une erreur car il ne recréera pas le type de la variable 

Lors de l'utilisation du mot clé ‘var’, le type est décidé par le compilateur au moment de la compilation, tandis que lors de l'utilisation du mot clé ‘dynamique’, le type est décidé au moment de l'exécution.

Le mot clé ‘var’ crée une variable locale fortement typée implicitement pour laquelle le compilateur est capable de déterminer le type à partir de l'expression d'initialisation - très utile lors de la programmation LINQ.

Le compilateur n'a aucune information sur le type dynamique de la variable. donc le compilateur ne montrera aucune intelligence.
Le compilateur a toutes les informations sur la valeur stockée du type var donc le compilateur montrera de l'intelligence.

Le type dynamique peut être passé en argument de fonction et la fonction peut également retourner un type objet
Mais
Le type var ne peut pas être passé en argument de fonction et la fonction ne peut pas retourner un type objet. Ce type de variable peut fonctionner dans la portée où il est défini.

0 votes

"Le compilateur créera v1 comme un entier" - quoi???

14voto

series0ne Points 4389

Var implique que la vérification de type statique (liaison précoce) est appliquée. dynamic implique que la vérification de type dynamique (liaison tardive) est appliquée. En termes de code, voici ce qu'il faut considérer :

class Junk
{
    public void Hello()
    {
        Console.WriteLine("Hello");
    }
}

class Program
{
    static void Main(String[] args)
    {
        var a = new Junk();
        dynamic b = new Junk();

        a.Hello();

        b.Hello();
    }
}

Si vous compilez cela et inspectez les résultats avec ILSpy, vous constaterez que le compilateur a ajouté du code de liaison tardive qui gérera l'appel à Hello() depuis b, alors que parce que la liaison précoce a été appliquée à a, a peut appeler Hello() directement.

par exemple (désassemblage ILSpy)

using System;
namespace ConsoleApplication1
{
    internal class Junk
    {
        public void Hello()
        {
            Console.WriteLine("Hello");
        }
    }
}

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
    internal class Program
    {
        [CompilerGenerated]
        private static class 

La meilleure chose à faire pour découvrir la différence est d'écrire vous-même une petite application console comme celle-ci, et de la tester vous-même avec ILSpy.

0 votes

Excellent exemple de base sur la façon dont IL les traite tous les deux après la compilation. Merci.

10voto

Shiva Mamidi Points 41

Voici un exemple simple qui démontre la différence entre Dynamic (4.0) et Var

dynamic  di = 20;
dynamic ds = "sadlfk";
var vi = 10;
var vsTemp= "sdklf";

Console.WriteLine(di.GetType().ToString());          //Affiche System.Int32
Console.WriteLine(ds.GetType().ToString());          //Affiche System.String
Console.WriteLine(vi.GetType().ToString());          //Affiche System.Int32
Console.WriteLine(vsTemp.GetType().ToString());      //Affiche System.String

**ds = 12;**   //ds est traité comme une chaîne de caractères jusqu'à ce stmt maintenant affecté entier.

Console.WriteLine(ds.GetType().ToString());          **//Affiche System.Int32**

**vs = 12**; //*Donne une erreur de compilation* - Voici la différence entre Var et Dynamic. var est une variable liée au temps de compilation.

Shiva Mamidi

3 votes

Mon impression est que la présence de caractères ** dans l'exemple de code est destinée à indiquer uniquement l'accentuation et n'est pas censée faire partie du code réel en fonctionnement.

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