Was ist der Unterschied zwischen dynamisch (C # 4) und var?


199

Ich hatte eine Menge Artikel über dieses neue Schlüsselwort gelesen, das mit C # v4 ausgeliefert wird, aber ich konnte den Unterschied zwischen "dynamisch" und "var" nicht erkennen.

Dieser Artikel hat mich zum Nachdenken gebracht, aber ich kann immer noch keinen Unterschied feststellen.

Können Sie "var" nur als lokale Variable verwenden, aber sowohl lokal als auch global dynamisch?

Könnten Sie Code ohne dynamisches Schlüsselwort anzeigen und dann denselben Code mit dynamischem Schlüsselwort anzeigen?

Antworten:


455

varist statisch typisiert - der Compiler und die Laufzeit kennen den Typ - sie ersparen Ihnen nur einige Eingaben ... die folgenden sind 100% identisch:

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

und

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

Alles, was passiert ist, war, dass der Compiler herausgefunden hat, dass ses sich um eine Zeichenfolge handeln muss (vom Initialisierer). In beiden Fällen weiß es (in der IL), dass s.Lengthdies die (Instanz-) string.LengthEigenschaft bedeutet.

dynamicist ein ganz anderes Tier; es ist am ähnlichsten object, aber mit dynamischem Versand:

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

Hier swird als dynamisch eingegeben . Er weiß über nicht string.Length, weil sie nicht wissen , etwas über sbei der Kompilierung. Zum Beispiel würde Folgendes auch kompiliert (aber nicht ausgeführt):

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

Zur Laufzeit (nur), wäre es überprüft die FlibbleBananaSnowballEigenschaft - nicht um es zu finden, und in einem Funkenregen explodieren.

Mit dynamicwerden Eigenschaften / Methoden / Operatoren / usw. zur Laufzeit basierend auf dem tatsächlichen Objekt aufgelöst. Sehr praktisch für Gespräche mit COM (das nur Laufzeit-Eigenschaften haben kann), dem DLR oder anderen dynamischen Systemen wie javascript.


3
Eine interessante Frage wäre, ob es dynamische Vorfahren statisch deklarierter Klassen gibt. Beispiel: Klasse X {public int Y {get; set;}} dynamic (X) s = GetSpecialX (); String-Test aufrufen = sY; würde einen Compilerfehler erzeugen, da der Compiler Y kennt, aber string test2 = sZ würde gut kompilieren und zur Laufzeit überprüft werden. Ich könnte mir viel Wert solcher halbedynamischen Klassen vorstellen!
mmmmmmmm

@rstevens - IIRC, Sie können dynamisches Verhalten über eine Schnittstelle hinzufügen (obwohl es keine direkte Sprachunterstützung für die Implementierung dynamischer Typen in C # gibt - nur deren Verwendung), also ist dies nicht unrealistisch ... oh, der Spaß, den wir haben könnten; - p
Marc Gravell

Obwohl es wichtig ist zu beachten, dass manchmal varTypen abgeleitet werden können, die aufgrund von Subtypen und impliziten Casts möglicherweise nicht erwünscht sind. Das heißt, varmöglicherweise wurde ein Typ statisch anders als erwartet aufgelöst, wenn implizite Umwandlungen auftreten (insbesondere auf einen allgemeineren Typ, der jedoch nicht darauf beschränkt ist). Ein triviales Beispiel ist object x = ""vs. var x = ""vs. var x = "" as object, aber andere hinterhältigere (und realistischere) Fälle können auftreten und subtile Fehler verursachen.

Um das gute Beispiel von Marc weiter zu erläutern, weiß der Compiler im ersten Fall (mit statischem Typ) genau, welche der vielen ÜberladungenWriteLine aufgerufen werden muss. Diese "Bindung" erfolgt zur Kompilierungszeit. Im Fall mit dynamicder Art der .Lengthmuss sein , dynamicauch, und es ist nicht bis zur Laufzeit entschieden wird , die Überlastung (wenn überhaupt) der WriteLineam besten paßt. Die Bindung erfolgt zur Laufzeit.
Jeppe Stig Nielsen

4
Wenn Sie den Mauszeiger über das varSchlüsselwort in Visual Studio bewegen, wird der tatsächliche Typ angezeigt, der abgeleitet wird. Zeigt an, dass der Typ zur Kompilierungszeit bekannt ist.
Christian Fredh

56

Mit var deklarierte Variablen sind implizit aber statisch typisiert. Mit dynamic deklarierte Variablen werden dynamisch typisiert. Diese Funktion wurde der CLR hinzugefügt, um dynamische Sprachen wie Ruby und Python zu unterstützen.

Ich sollte hinzufügen, dass dies bedeutet, dass dynamische Deklarationen zur Laufzeit und var- Deklarationen zur Kompilierungszeit aufgelöst werden.


42

Ich werde den Unterschied zwischen dynamisch und var erklären .

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

Das wird funktionieren. Der Compiler kann den Typ der dynamischen Variablen neu erstellen .
Zuerst wird der Typ als Ganzzahl erstellt, und danach wird der Compiler den Typ als Zeichenfolge neu erstellen,
jedoch im Fall von 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 


Bei Verwendung des Schlüsselworts ' var ' wird der Typ beim Kompilieren vom Compiler festgelegt, während bei Verwendung des Schlüsselworts ' dynamic ' der Typ von der Laufzeit bestimmt wird.
Das Schlüsselwort ' var ' ist eine stark implizit typisierte lokale Variable, für die der Compiler den Typ anhand des Initialisierungsausdrucks bestimmen kann - sehr nützlich bei der LINQ-Programmierung.
Der Compiler hat keine Informationen über den dynamischen Variablentyp. Der Compiler zeigt also keine Intelligenz an.
Der Compiler verfügt über alle Informationen zum gespeicherten Wert vom Typ var, sodass der Compiler Informationen anzeigt.
dynamischer Typ kann auch Objekttyp zurückgeben kann als Funktionsargument und Funktion übergeben wird
aber
var Typ als Funktionsargument und Funktion nicht zurückgeben kann nicht Objekttyp übergeben werden kann. Dieser Variablentyp kann in dem Bereich arbeiten, in dem er definiert wurde.


14

var impliziert, dass die statische Typprüfung (frühe Bindung) angewendet wird. Dynamisch bedeutet, dass die dynamische Typprüfung (späte Bindung) angewendet wird. Beachten Sie in Bezug auf den Code Folgendes:

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

Wenn Sie dies kompilieren und die Ergebnisse mit ILSpy überprüfen, werden Sie feststellen, dass der Compiler einen späten Bindungscode hinzugefügt hat, der den Aufruf von Hello () von b verarbeitet, während a Hello aufrufen kann, da eine frühe Bindung auf a angewendet wurde () direkt.

zB (ILSpy-Demontage)

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

Das Beste, was Sie tun können, um den Unterschied zu entdecken, ist, sich eine kleine Konsolen-App wie diese zu schreiben und sie selbst mit ILSpy zu testen.


Ein großartiges grundlegendes Beispiel dafür, wie IL beide nach der Kompilierung behandelt. Vielen Dank.
Könige

12

Ein großer Unterschied - Sie können einen dynamischen Rückgabetyp haben.

dynamic Foo(int x)
{
    dynamic result;

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

    return result;
}

10

Hier ist ein einfaches Beispiel, das den Unterschied zwischen Dynamic (4.0) und Var zeigt

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
Mein Eindruck ist, dass das Vorhandensein von **Zeichen im Codebeispiel nur die Betonung anzeigen soll und nicht Teil des echten Arbeitscodes sein soll.
DavidRR

7

var ist nur eine Abkürzung für eine normale Typdeklaration, bei der Sie den Compiler den richtigen Typ erraten lassen.

dynamic ist ein neuer (statischer) Typ, bei dem alle Überprüfungen zur Laufzeit und nicht vom Compiler durchgeführt werden.


4

Der Typ einer mit var deklarierten Variablen wird vom Compiler festgelegt. Dies ist eine Verknüpfung zur Angabe des Typnamens, nicht mehr.

Unabhängig davon, wie dynamisch die Laufzeit ist, hat der Compiler keine Ahnung vom tatsächlichen Typ, und alle Methoden- / Feld- / Eigenschaftenzugriffe mit dieser Variablen werden zur Laufzeit ausgearbeitet.


3

Dies ist ein schönes Youtube-Video, das mit praktischer Demonstration über varVS spricht Dynamic.

Unten finden Sie eine detailliertere Erklärung mit Schnappschuss.

Var wird früh gebunden (statisch überprüft), während dynamisch spät gebunden wird (dynamisch ausgewertet).

Das Schlüsselwort Var betrachtet Ihre Daten auf der rechten Seite und entscheidet dann während der Kompilierungszeit über den Datentyp auf der linken Seite. Mit anderen Worten, das Schlüsselwort var erspart Ihnen nur die Eingabe vieler Dinge. Schauen Sie sich das folgende Bild an, in dem, wenn wir Zeichenfolgendaten angegeben haben und die Variable x den Zeichenfolgendatentyp in meinem Tooltip anzeigt.

Geben Sie hier die Bildbeschreibung ein

Andererseits dient das dynamische Schlüsselwort einem völlig anderen Zweck. Dynamische Objekte werden zur Laufzeit ausgewertet. Zum Beispiel ist im folgenden Code die Eigenschaft "Länge" vorhanden oder wird zur Laufzeit nicht ausgewertet. Ich habe absichtlich ein kleines "l" eingegeben, daher hat dieses Programm gut kompiliert, aber als es tatsächlich ausgeführt wurde, hat es einen Fehler ausgelöst, wenn die Eigenschaft "Länge" wurde genannt (SMALL "l").

Geben Sie hier die Bildbeschreibung ein


2

Die dynamische Variable und die Variable var können beide Werttypen speichern, müssen jedoch zum Zeitpunkt der Deklaration 'var' initialisieren.

Der Compiler hat keine Informationen über den Variablentyp 'dynamisch'. var ist compilersicher, dh der Compiler verfügt über alle Informationen zum gespeicherten Wert, sodass zur Laufzeit keine Probleme auftreten.

Der dynamische Typ kann als Funktionsargument übergeben werden und die Funktion kann ihn auch zurückgeben. Der Var-Typ kann nicht als Funktionsargument übergeben werden, und die Funktion kann den Objekttyp nicht zurückgeben. Dieser Variablentyp kann in dem Bereich arbeiten, in dem er definiert wurde.

Im Falle einer dynamischen Umwandlung ist keine Umwandlung erforderlich, aber Sie müssen die Eigenschaften und Methoden in Bezug auf den gespeicherten Typ kennen, während für var keine Umwandlung erforderlich ist, da der Compiler über alle Informationen verfügt, um die Operation auszuführen.

dynamisch: Nützlich beim Codieren mit Reflection oder dynamischer Sprachunterstützung oder mit den COM-Objekten, da weniger Code geschrieben werden muss.

var: Nützlich, wenn Ergebnisse aus den Linq-Abfragen abgerufen werden sollen. In 3.5 Framework wird die Unterstützung der Linq-Funktion eingeführt.

Referenz: Counsellingbyabhi


2
  1. Var und Dynamic definieren den Typ.
  2. var zur Kompilierungszeit, während dynamische zur Laufzeit sind.
  3. In der var-Deklaration und -Initialisierung sind beide obligatorisch wie die konstante Variable while
  4. in der dynamischen Initialisierung kann zur Laufzeit wie schreibgeschützte Variablen sein.
  5. in var type kann jeder Typ, der zum Zeitpunkt der Initialisierung festgelegt wird, aber nicht als nächstes geändert werden
  6. dynamic kann jeden Typ annehmen, auch wenn der Benutzer einen Datentyp definiert.

1

Verwechseln Sie nicht dynamisch und var. Das Deklarieren einer lokalen Variablen mit var ist nur eine syntaktische Verknüpfung, bei der der Compiler den spezifischen Datentyp aus einem Ausdruck ableitet. Das Schlüsselwort var kann nur zum Deklarieren lokaler Variablen innerhalb einer Methode verwendet werden, während das dynamische Schlüsselwort für lokale Variablen, Felder und Argumente verwendet werden kann. Sie können einen Ausdruck nicht in var umwandeln, aber Sie können einen Ausdruck in dynamic umwandeln. Sie müssen eine mit var deklarierte Variable explizit initialisieren, während Sie eine mit dynamic deklarierte Variable nicht initialisieren müssen.


1
  1. Das Schlüsselwort Var (implizit typisierte lokale Variable) wird verwendet, um lokale Variablen zu definieren. Im Fall von Var wird der zugrunde liegende Datentyp zur Kompilierungszeit selbst basierend auf der anfänglichen Zuweisung bestimmt. Sobald die anfängliche Zuweisung mit dem Var-Typ vorgenommen wurde, wird dies der Fall sein wird stark typisiert. Wenn Sie versuchen, einen inkompatiblen Wert mit dem Var-Typ zu speichern, führt dies zu einem Fehler bei der Kompilierung.

Beispiel:

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.

Im dynamischen Typ wird der zugrunde liegende Typ jedoch nur zur Laufzeit bestimmt. Der dynamische Datentyp wird zur Kompilierungszeit nicht überprüft und auch nicht stark typisiert. Wir können einen beliebigen Anfangswert für den dynamischen Typ zuweisen und ihn dann einem neuen Typ zuweisen Wert während seiner Lebensdauer.

Beispiel:

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]

Es bietet auch keine IntelliSense-Unterstützung. Es bietet keine bessere Unterstützung, wenn wir auch mit linq arbeiten. Weil es keine Lambda-Ausdrücke, Erweiterungsmethoden und anonymen Methoden unterstützt.


1

Hier sind die Unterschiede

  • var ist statisch typisiert (Kompilierungszeit), dynamic ist dynamisch typisiert (Laufzeit)

  • Eine als var deklarierte Variable kann nur lokal verwendet werden. Dynamische Variablen können als Parameter an function übergeben werden (Funktionssignatur kann einen Parameter als dynamisch definieren, nicht jedoch als var).

  • Bei dynamic erfolgt die Auflösung der Eigenschaften zur Laufzeit. Dies ist bei var nicht der Fall. Dies bedeutet, dass zur Kompilierungszeit jede als dynamisch deklarierte Variable eine Methode aufrufen kann, die möglicherweise vorhanden ist oder nicht, sodass der Compiler keinen Fehler auslöst.

  • Typumwandlung mit var nicht möglich, aber mit dynamisch möglich (Sie können ein Objekt als dynamisch, aber nicht als var umwandeln).

Arun Vijayraghavan

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.