Qual è la differenza tra dinamico (C # 4) e var?


199

Avevo letto un sacco di articoli su quella nuova parola chiave che viene distribuita con C # v4, ma non sono riuscito a distinguere tra "dinamico" e "var".

Questo articolo mi ha fatto riflettere, ma non riesco ancora a vedere alcuna differenza.

È possibile utilizzare "var" solo come variabile locale, ma dinamico come locale e globale?

Potresti mostrare un po 'di codice senza una parola chiave dinamica e quindi mostrare lo stesso codice con una parola chiave dinamica?

Risposte:


455

varè di tipo statico - il compilatore e il runtime conoscono il tipo - ti fanno solo risparmiare un po 'di battitura ... i seguenti sono identici al 100%:

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

e

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

Tutto ciò che è accaduto è stato che il compilatore ha capito che sdeve essere una stringa (dall'inizializzatore). In entrambi i casi, sa (nell'IL) che s.Lengthsignifica la string.Lengthproprietà (istanza) .

dynamicè una bestia molto diversa; è molto simile a object, ma con spedizione dinamica:

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

Qui, sviene digitato come dinamico . Essa non conosce string.Length, perché non sa nulla riguardo sal momento della compilazione. Ad esempio, compilerebbe (ma non eseguirà) anche quanto segue:

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

In fase di esecuzione (solo), verificherebbe la FlibbleBananaSnowballproprietà, non riuscendo a trovarla ed esploderebbe in una pioggia di scintille.

Con dynamic, proprietà / metodi / operatori / ecc vengono risolti in fase di esecuzione , in base all'oggetto reale. Molto utile per parlare con COM (che può avere proprietà solo di runtime), il DLR o altri sistemi dinamici, come javascript.


3
Una domanda interessante sarebbe se ci sono antenati dinamici di classi dichiarate staticamente. Esempio: class X {public int Y {get; set;}} dynamic (X) s = GetSpecialX (); Chiamata stringa test = sY; genererebbe un errore del compilatore perché il compilatore è a conoscenza di Y ma la stringa test2 = sZ si compila bene e verrebbe controllata in fase di esecuzione. Potrei pensare a molto valore di classi così semi-dinamiche!
mmmmmmmm,

@rstevens - IIRC, puoi aggiungere un comportamento dinamico tramite un'interfaccia (anche se non esiste un supporto linguistico diretto per l'implementazione di tipi dinamici in C # - solo consumandoli), quindi questo non è irrealistico ... oh il divertimento che potremmo avere; - p
Marc Gravell

Anche se è importante notare che a volte è varpossibile inferire tipi che potrebbero non essere desiderati a causa di sottotipi e cast impliciti. Cioè, varpotrebbe aver risolto un tipo staticamente diverso dal previsto quando si verificano cast impliciti (in particolare a un tipo più generale, ma non è limitato a questo). Un esempio banale è object x = ""vs. var x = ""vs. var x = "" as object, ma possono verificarsi altri casi più subdoli (e realistici) che possono causare bug sottili.

Per approfondire il buon esempio di Marc, nel primo caso (con tipo statico), il compilatore sa esattamente quale dei molti sovraccarichi diWriteLine chiamare. Questa "associazione" avviene durante la compilazione. Nel caso in cui dynamic, anche il tipo di .Lengthdeve essere dynamic, e non è fino al runtime che si decide quale sovraccarico (se del caso) si WriteLineadatta meglio. Il binding avviene in fase di esecuzione.
Jeppe Stig Nielsen,

4
Quando si passa il mouse sulla varparola chiave in Visual Studio, viene visualizzato il tipo effettivo che viene inferito. Indica che il tipo è noto al momento della compilazione.
Christian Fredh,

56

Le variabili dichiarate con var sono implicite ma tipizzate staticamente . Le variabili dichiarate con dinamico sono tipizzate dinamicamente. Questa funzionalità è stata aggiunta al CLR per supportare linguaggi dinamici come Ruby e Python.

Dovrei aggiungere che ciò significa che le dichiarazioni dinamiche vengono risolte in fase di esecuzione, mentre le dichiarazioni var vengono risolte in fase di compilazione.


42

Spiegherò la differenza tra dinamico e var .

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

Questo funzionerà. il compilatore può ricreare il tipo di variabile dinamica .
prima crea il tipo come numero intero e dopo quel compilatore ricrea il tipo come stringa
ma in caso di var

var v1;  // Compiler will throw error because we have to initialized at the time of declaration  
var v2 = 1; // Compiler will create v1 as **integer**
v2 = "Suneel Gupta"; // Compiler will throw error because, compiler will not recreate the type of variable 


Quando si utilizza la parola chiave " var ", il tipo viene deciso dal compilatore in fase di compilazione, mentre quando si utilizza la parola chiave " dinamica ", il tipo viene deciso dal runtime.
parola chiave ' var ', una variabile locale tipizzata in modo fortemente implicito per la quale il compilatore è in grado di determinare il tipo dall'espressione di inizializzazione, molto utile quando si esegue la programmazione LINQ.
Il compilatore non ha alcuna informazione sul tipo dinamico di variabile. quindi il compilatore non mostrerà alcuna intelligenza.
il compilatore ha tutte le informazioni sul valore memorizzato del tipo var, quindi il compilatore mostrerà intelligenza.
il tipo dinamico può essere passato come argomento della funzione e anche la funzione può restituire il tipo di oggetto
Ma il tipo
var non può essere passato come argomento della funzione e la funzione non può restituire il tipo di oggetto. Questo tipo di variabile può funzionare nell'ambito in cui è stato definito.


14

var implica che viene applicato il controllo del tipo statico (associazione anticipata). dinamico implica che sia applicato il controllo dinamico del tipo (late binding). In termini di codice, considera quanto segue:

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();
    }
}

Se lo compili e controlli i risultati con ILSpy, scoprirai che il compilatore ha aggiunto del codice di associazione tardiva che gestirà la chiamata a Hello () da b, mentre perché è stata applicata l'associazione anticipata a a, a è in grado di chiamare Hello () direttamente.

ad es. (disassemblaggio 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 <Main>o__SiteContainer0
        {
            public static CallSite<Action<CallSite, object>> <>p__Site1;
        }
        private static void Main(string[] args)
        {
            Junk a = new Junk();      //NOTE: Compiler converted var to Junk
            object b = new Junk();    //NOTE: Compiler converted dynamic to object
            a.Hello();  //Already Junk so just call the method.

                          //NOTE: Runtime binding (late binding) implementation added by compiler.
            if (Program.<Main>o__SiteContainer0.<>p__Site1 == null)
            {
                Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "Hello", null, typeof(Program), new CSharpArgumentInfo[]
                {
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                }));
            }
            Program.<Main>o__SiteContainer0.<>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, b);
        }
    }
}

La cosa migliore che puoi fare per scoprire la differenza è scrivere una piccola app console come questa e testarla tu stesso con ILSpy.


ottimo esempio di base su come IL li tratta entrambi dopo la compilazione. Grazie.
Re

12

Una grande differenza: puoi avere un tipo di ritorno dinamico.

dynamic Foo(int x)
{
    dynamic result;

    if (x < 5)
      result = x;
    else
      result = x.ToString();

    return result;
}

10

Ecco un semplice esempio che dimostra la differenza tra Dynamic (4.0) e Var

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

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

**ds = 12;**   //ds is treated as string until this stmt now assigning integer.

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

**vs = 12**; //*Gives compile time error* - Here is the difference between Var and Dynamic. var is compile time bound variable.

Shiva Mamidi


2
La mia impressione è che la presenza di **caratteri nell'esempio di codice abbia lo scopo di indicare solo l'enfasi e non di far parte del vero codice di lavoro.
DavidRR

7

var è solo una scorciatoia per una normale dichiarazione di tipo, in cui si consente al compilatore di indovinare il tipo corretto.

dynamic è un nuovo tipo (statico), in cui tutti i controlli vengono eseguiti in fase di esecuzione, non dal compilatore.


4

Il tipo di una variabile dichiarata con var è determinata dal compilatore, è una scorciatoia per specificare il nome del tipo, niente di più.

Tuttavia, la dinamica viene determinata in fase di esecuzione, il compilatore non ha idea del tipo effettivo e tutti gli accessi al metodo / campo / proprietà con quella variabile verranno elaborati in fase di esecuzione.


3

Questo è un bel video di YouTube che parla di varVS Dynamiccon dimostrazioni pratiche.

Di seguito è una spiegazione più dettagliata con istantanea.

Il var è associato anticipatamente (controllato staticamente) mentre il dinamico è associato in ritardo (valutato dinamicamente).

La parola chiave var esamina i dati sul lato destro e quindi, durante il tempo di compilazione, decide il tipo di dati sulla mano sinistra. In altre parole, la parola chiave var consente solo di salvare molte cose. Dai un'occhiata all'immagine qui sotto dove quando abbiamo dato i dati di stringa e la variabile x mostra il tipo di dati di stringa nel mio suggerimento.

inserisci qui la descrizione dell'immagine

D'altra parte, la parola chiave dinamica ha uno scopo completamente diverso. Gli oggetti dinamici vengono valutati durante il runtime. Ad esempio nel codice seguente la proprietà "Lunghezza" esiste o no viene valutata durante il runtime. Ho volutamente digitato una piccola "l", quindi questo programma è stato compilato correttamente ma quando è stato effettivamente eseguito ha generato un errore quando la proprietà "lunghezza" è stato chiamato (PICCOLO "l").

inserisci qui la descrizione dell'immagine


2

la variabile dinamica e la variabile var possono entrambe archiviare qualsiasi tipo di valore ma è necessario inizializzare 'var' al momento della dichiarazione.

Il compilatore non ha alcuna informazione sul tipo "dinamico" di variabile. var è sicuro per il compilatore, ovvero il compilatore ha tutte le informazioni sul valore memorizzato, in modo che non causi alcun problema in fase di esecuzione.

Il tipo dinamico può essere passato come argomento di funzione e anche la funzione può restituirlo. Il tipo var non può essere passato come argomento della funzione e la funzione non può restituire il tipo di oggetto. Questo tipo di variabile può funzionare nell'ambito in cui è stato definito.

In caso di Casting dinamico non è richiesto ma è necessario conoscere la proprietà e i metodi relativi al tipo memorizzato, mentre per var Non è necessario eseguire il cast perché il compilatore ha tutte le informazioni per eseguire l'operazione.

dinamico: utile quando si codifica utilizzando il supporto del linguaggio riflesso o dinamico o con gli oggetti COM, poiché è necessario scrivere una quantità minore di codice.

var: utile quando si ottengono risultati dalle query linq. In 3.5 framework introduce per supportare la funzione linq.

Riferimento: Counsellingbyabhi


2
  1. Var e dinamico definiscono il tipo.
  2. var al momento della compilazione mentre dinamico è in fase di esecuzione.
  3. nella dichiarazione var e inizializzazione entrambi sono obbligatori come variabile costante while
  4. nell'inizializzazione dinamica può essere in fase di esecuzione come variabili di sola lettura.
  5. nel tipo var qualsiasi tipo deciso al momento l'inizializzazione non può cambiare ma
  6. dinamico può adottare qualsiasi tipo anche l'utente definisce anche il tipo di dati.

1

Non confondere dinamico e var. Dichiarare una variabile locale usando var è solo un collegamento sintattico che consente al compilatore di dedurre il tipo di dati specifico da un'espressione. La parola chiave var può essere utilizzata solo per dichiarare variabili locali all'interno di un metodo, mentre la parola chiave dinamica può essere utilizzata per variabili, campi e argomenti locali. Non puoi lanciare un'espressione su var, ma puoi lanciare un'espressione su dinamica. È necessario inizializzare esplicitamente una variabile dichiarata utilizzando var mentre non è necessario inizializzare una variabile dichiarata con dinamico.


1
  1. La parola chiave Var (Variabile locale tipizzata implicita) viene utilizzata per definire le variabili locali. Nel caso di Var, il tipo di dati sottostante viene determinato al momento della compilazione stesso in base all'assegnazione iniziale. Una volta che l'assegnazione iniziale è stata effettuata con il tipo Var, quindi diventerà fortemente tipizzato. Se si tenta di memorizzare qualsiasi valore incompatibile con il tipo Var, si verificherà un errore di tempo di compilazione.

Esempio:

Var strNameList=new List<string>(); By using this statement we can store list of names in the string format. 
strNameList.add("Senthil");
strNameList.add("Vignesh");

strNameList.add(45); // This statement will cause the compile time error.

Ma nel tipo dinamico, il tipo sottostante viene determinato solo in fase di esecuzione. Il tipo di dati dinamico non viene verificato in fase di compilazione e inoltre non è fortemente tipizzato. È possibile assegnare qualsiasi valore iniziale per il tipo dinamico e quindi può essere riassegnato a qualsiasi nuovo valore durante la sua vita.

Esempio:

dynamic test="Senthil";
Console.Writeline(test.GetType())  // System.String

test=1222;
Console.Writeline(test.GetType())  // System.Int32

test=new List<string>();
Console.Writeline(test.GetType())  //System.Collections.Generic.List'1[System.String]

Inoltre non fornisce supporto IntelliSense e non fornisce un supporto migliore anche quando forniamo lavoro con linq, poiché non supporta espressioni lambda, metodi di estensione e metodi anonimi.


1

Ecco le differenze

  • var è tipizzato staticamente (tempo di compilazione), dinamico è digitato dinamicamente (tempo di esecuzione)

  • Una variabile dichiarata come var può essere utilizzata solo localmente, le variabili dinamiche possono essere passate come parametri per funzionare (la firma della funzione può definire un parametro come dinamico ma non var).

  • con dynamic la risoluzione delle proprietà avviene in fase di runtime e non è il caso di var, il che significa che al momento della compilazione qualsiasi variabile dichiarata come dinamica può chiamare un metodo che potrebbe o non potrebbe esistere e quindi il compilatore non genererebbe un errore.

  • Digita casting con var non possibile ma con dinamico è possibile (puoi lanciare un oggetto come dinamico ma non come var).

Arun Vijayraghavan

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.