Apa perbedaan antara dinamis (C # 4) dan var?

199

Saya telah membaca banyak artikel tentang kata kunci baru yang dikirimkan dengan C # v4, tetapi saya tidak dapat melihat perbedaan antara "dinamis" dan "var".

Artikel ini membuat saya berpikir tentang hal itu, tetapi saya masih tidak melihat perbedaan.

Apakah Anda dapat menggunakan "var" hanya sebagai variabel lokal, tetapi dinamis baik sebagai lokal maupun global?

Bisakah Anda menampilkan beberapa kode tanpa kata kunci dinamis dan kemudian menunjukkan kode yang sama dengan kata kunci dinamis?

Ivan Prodanov
sumber

Jawaban:

455

vardiketik statis - kompiler dan runtime tahu jenisnya - mereka hanya menghemat beberapa pengetikan ... berikut ini 100% identik:

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

dan

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

Semua yang terjadi adalah bahwa compiler tahu itu sharus berupa string (dari initializer). Dalam kedua kasus, ia tahu (dalam IL) yang s.Lengthberarti properti (instance) string.Length.

dynamicadalah binatang yang sangat berbeda; ini paling mirip dengan object, tetapi dengan pengiriman dinamis:

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

Di sini, sdiketik sebagai dinamis . Tidak tahu string.Length, karena tidak tahu apa - apa tentang swaktu kompilasi. Misalnya, berikut ini akan mengkompilasi (tetapi tidak berjalan) juga:

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

Pada saat runtime (hanya), itu akan memeriksa untuk FlibbleBananaSnowballproperti - gagal untuk menemukannya, dan meledak di mandi bunga api.

Dengan dynamic, properti / metode / operator / dll diselesaikan pada saat runtime , berdasarkan objek yang sebenarnya. Sangat berguna untuk berbicara dengan COM (yang dapat memiliki sifat runtime-only), DLR, atau sistem dinamis lainnya javascript.

Marc Gravell
sumber
3
Pertanyaan yang menarik adalah apakah ada leluhur dinamis dari kelas yang dideklarasikan secara statis. Contoh: kelas X {public int Y {get; set;}} dynamic (X) s = GetSpecialX (); Tes string panggilan = sY; akan menghasilkan kesalahan kompiler karena kompiler tahu tentang Y tetapi string test2 = sZ akan mengkompilasi dengan baik dan diperiksa pada saat run-time. Saya bisa memikirkan banyak nilai dari kelas setengah dinamis seperti itu!
mmmmmmmm
@rstevens - IIRC, Anda dapat menambahkan perilaku dinamis melalui antarmuka (walaupun tidak ada dukungan bahasa langsung untuk menerapkan tipe dinamis di C # - hanya mengkonsumsinya), jadi ini bukan tidak realistis ... oh kesenangan yang bisa kita miliki; - p
Marc Gravell
Meskipun penting untuk dicatat bahwa kadang-kadang vardapat menyimpulkan jenis yang mungkin tidak diinginkan karena subtipe dan gips tersirat. Artinya, varmungkin telah menyelesaikan jenis yang secara statis berbeda dari yang diharapkan ketika gips implisit terjadi (terutama untuk jenis yang lebih umum, tetapi tidak terbatas pada ini). Contoh sepele adalah object x = ""vs. var x = ""vs. var x = "" as object, tetapi kasus lain yang lebih licik (dan realistis) dapat terjadi dan dapat menyebabkan bug halus.
Untuk menguraikan lebih jauh pada contoh Marc yang baik, dalam kasus pertama (dengan tipe statis), kompiler tahu persis mana dari banyak kelebihanWriteLine panggilan. Ini "mengikat" terjadi waktu kompilasi. Dalam kasus dengan dynamic, jenis .Lengthharus dynamicterlalu, dan tidak sampai run-time diputuskan yang kelebihan (jika ada sama sekali) yang WriteLinepaling cocok. Binding terjadi saat run-time.
Jeppe Stig Nielsen
4
Saat Anda mengarahkan varkata kunci di Visual Studio, tipe aktual ditampilkan yang disimpulkan. Menunjukkan kepada Anda bahwa jenisnya diketahui pada waktu kompilasi.
Christian Fredh
56

Variabel yang dideklarasikan dengan var secara implisit tetapi diketik secara statis . Variabel yang dideklarasikan dengan dinamis diketik secara dinamis. Kemampuan ini ditambahkan ke CLR untuk mendukung bahasa dinamis seperti Ruby dan Python.

Saya harus menambahkan bahwa ini berarti bahwa deklarasi dinamis diselesaikan pada saat run-time, deklarasi var diselesaikan pada waktu kompilasi.

Hans Van Slooten
sumber
42

Saya akan menjelaskan perbedaan antara dinamis dan var .

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

Ini akan bekerja kompiler dapat membuat kembali jenis variabel dinamis .
pertama-tama ia membuat tipe sebagai integer dan setelah itu kompiler akan membuat kembali tipe sebagai string
tetapi dalam kasus 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 


Saat menggunakan kata kunci ' var ', jenisnya ditentukan oleh kompiler pada waktu kompilasi, sedangkan saat menggunakan kata kunci ' dinamis ', jenisnya ditentukan oleh runtime.
' Var ' kata kunci, variabel lokal sangat diketik implisit yang compiler dapat menentukan jenis dari ekspresi inisialisasi - sangat berguna ketika melakukan pemrograman LINQ.
Compiler tidak memiliki informasi tentang jenis variabel dinamis . jadi kompiler tidak akan menunjukkan kecerdasan apa pun.
compiler memiliki semua informasi tentang nilai tersimpan tipe var sehingga kompiler akan menunjukkan kecerdasan.
tipe dinamis dapat diteruskan sebagai argumen fungsi dan fungsi juga dapat mengembalikan tipe objek
Tapi tipe
var tidak dapat diteruskan sebagai argumen fungsi dan fungsi tidak dapat mengembalikan tipe objek. Jenis variabel ini dapat bekerja dalam lingkup di mana ia didefinisikan.

Suneel Gupta
sumber
14

var menyiratkan bahwa pengecekan tipe statis (penjilidan awal) diterapkan. dynamic menyiratkan bahwa pengecekan tipe dinamis (late binding) diterapkan. Dalam hal kode, pertimbangkan hal berikut:

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

Jika Anda mengompilasi ini dan memeriksa hasilnya dengan ILSpy, Anda akan menemukan bahwa kompiler telah menambahkan beberapa kode pengikatan akhir yang akan menangani panggilan ke Hello () dari b, sedangkan karena pengikatan awal diterapkan ke a, a dapat memanggil Hello () secara langsung.

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

Hal terbaik yang dapat Anda lakukan untuk menemukan perbedaannya adalah menulis sendiri aplikasi konsol kecil seperti ini, dan mengujinya sendiri dengan ILSpy.

Matthew Layton
sumber
contoh dasar yang bagus tentang bagaimana IL memperlakukan keduanya setelah kompilasi. Terima kasih.
Raja
12

Satu perbedaan besar - Anda dapat memiliki tipe pengembalian dinamis.

dynamic Foo(int x)
{
    dynamic result;

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

    return result;
}
pengguna2382351
sumber
10

Berikut adalah contoh sederhana yang menunjukkan perbedaan antara Dynamic (4.0) dan 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.

Siwa Mamidi

Siwa Mamidi
sumber
2
Kesan saya adalah bahwa kehadiran **karakter dalam contoh kode dimaksudkan untuk menunjukkan penekanan saja dan tidak dimaksudkan untuk menjadi bagian dari kode kerja nyata.
DavidRR
7

var hanyalah singkatan untuk deklarasi tipe normal, di mana Anda membiarkan kompiler menebak tipe yang benar.

dynamic adalah tipe baru (statis), di mana semua pemeriksaan dilakukan pada saat runtime, bukan oleh kompiler.

Gimel
sumber
4

Tipe variabel yang dideklarasikan dengan var ditentukan oleh kompiler, itu adalah jalan pintas untuk menentukan nama tipe, tidak lebih.

Namun dinamis ditentukan saat runtime, kompiler tidak tahu jenis sebenarnya, dan semua metode / bidang / properti mengakses dengan variabel itu akan dikerjakan saat runtime.

Richard
sumber
3

Ini adalah video youtube yang bagus yang berbicara tentang varVS Dynamicdengan peragaan praktis.

Di bawah ini adalah penjelasan yang lebih rinci dengan snapshot.

Var diikat awal (diperiksa secara statis) sementara dinamis diikat lebih lambat (dievaluasi secara dinamis).

Kata kunci var melihat data sisi kanan Anda dan kemudian selama waktu kompilasi menentukan jenis data tangan kiri. Dengan kata lain var kata kunci hanya menghemat Anda mengetik banyak hal. Lihat gambar di bawah ini di mana ketika kami telah memberikan data string dan variabel x menunjukkan tipe data string di tip alat saya.

masukkan deskripsi gambar di sini

Di sisi lain, kata kunci dinamis untuk tujuan yang sama sekali berbeda. Objek dinamis dievaluasi selama runtime. Misalnya dalam kode di bawah ini properti "Panjang" ada atau tidak dievaluasi selama runtime. Saya sengaja mengetik "l" kecil, jadi program ini dikompilasi dengan baik tetapi ketika benar-benar dieksekusi itu memunculkan kesalahan ketika properti "panjang" disebut (KECIL "l").

masukkan deskripsi gambar di sini

Shivprasad Koirala
sumber
2

variabel dinamis dan variabel var keduanya dapat menyimpan semua jenis nilai tetapi diperlukan untuk menginisialisasi 'var' pada saat deklarasi.

Compiler tidak memiliki informasi tentang tipe variabel 'dinamis'. var adalah kompiler aman yaitu kompiler memiliki semua informasi tentang nilai yang disimpan, sehingga tidak menyebabkan masalah saat dijalankan.

Tipe dinamis dapat diteruskan sebagai argumen fungsi dan fungsi juga dapat mengembalikannya. Jenis Var tidak dapat diteruskan sebagai argumen fungsi dan fungsi tidak dapat mengembalikan jenis objek. Jenis variabel ini dapat bekerja dalam lingkup di mana ia didefinisikan.

Dalam hal Pengecoran dinamis tidak diperlukan tetapi Anda perlu mengetahui properti dan metode yang terkait dengan tipe tersimpan, sedangkan untuk var Tidak perlu melakukan casting karena kompiler memiliki semua informasi untuk melakukan operasi.

dynamic: Berguna saat pengkodean menggunakan refleksi atau dukungan bahasa dinamis atau dengan objek COM, karena kita perlu menulis lebih sedikit kode.

var: Berguna saat mendapatkan hasil dari permintaan LINQ. Dalam kerangka 3.5 itu memperkenalkan untuk mendukung fitur LINQ.

Referensi: Counsellingbyabhi

Abhishek Gahlout
sumber
2
  1. Var dan tipe define dinamis.
  2. var pada waktu kompilasi sementara dinamis berada di run time.
  3. dalam deklarasi dan inisialisasi var keduanya wajib seperti variabel konstan sementara
  4. dalam inisialisasi dinamis dapat dijalankan pada waktu seperti variabel readonly.
  5. dalam tipe var jenis apa pun yang diputuskan pada saat inisialisasi tidak dapat berubah tetapi selanjutnya
  6. dinamis dapat mengadopsi tipe apa pun, bahkan pengguna juga menentukan tipe data.
shhhhh
sumber
1

Jangan bingung antara dinamis dan var. Mendeklarasikan variabel lokal menggunakan var hanyalah pintasan sintaksis yang membuat kompiler menyimpulkan tipe data spesifik dari ekspresi. Kata kunci var hanya dapat digunakan untuk mendeklarasikan variabel lokal di dalam suatu metode sementara kata kunci dinamis dapat digunakan untuk variabel lokal, bidang, dan argumen. Anda tidak bisa memberikan ekspresi ke var, tetapi Anda bisa memberikan ekspresi ke dinamis. Anda harus secara eksplisit menginisialisasi variabel yang dideklarasikan menggunakan var sementara Anda tidak harus menginisialisasi variabel yang dideklarasikan dengan dinamis.

Kartik M
sumber
1
  1. Kata kunci Var (Variabel lokal diketik implisit) digunakan untuk mendefinisikan variabel lokal. Dalam kasus Var, tipe data yang mendasarinya ditentukan pada waktu kompilasi itu sendiri berdasarkan penugasan awal. Setelah penugasan awal telah dibuat dengan tipe Var, maka akan menjadi sangat diketik. Jika Anda mencoba untuk menyimpan nilai yang tidak kompatibel dengan tipe Var itu akan menghasilkan kesalahan waktu kompilasi.

Contoh:

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.

Tetapi dalam tipe Dinamis, tipe yang mendasarinya ditentukan hanya pada waktu berjalan. Tipe data dinamis tidak dicentang pada waktu kompilasi dan juga tidak diketik dengan kuat. Kami dapat menetapkan nilai awal apa pun untuk tipe dinamis dan kemudian dapat dipindahkan ke yang baru nilai selama waktu hidupnya.

Contoh:

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]

Itu tidak memberikan dukungan IntelliSense juga. Tidak memberikan dukungan yang lebih baik ketika kami bekerja dengan linq juga. Karena itu tidak mendukung ekspresi lambda, metode ekstensi dan metode anonim.

kuttychutty
sumber
1

Inilah perbedaannya

  • var diketik secara statis (waktu kompilasi), dinamis diketik secara dinamis (waktu berjalan)

  • Variabel yang dideklarasikan sebagai var hanya dapat digunakan secara lokal, variabel dinamis dapat diteruskan sebagai params berfungsi (tanda tangan fungsi dapat mendefinisikan param sebagai dinamis tetapi tidak var).

  • dengan dinamis resolusi properti terjadi pada saat runtime dan tidak demikian halnya dengan var yang berarti pada waktu kompilasi, variabel apa pun yang dideklarasikan sebagai dinamis dapat memanggil metode yang mungkin ada atau tidak ada sehingga kompiler tidak akan membuat kesalahan.

  • Ketik casting dengan var tidak mungkin tetapi dengan dinamis itu mungkin (Anda dapat melemparkan objek sebagai dinamis tetapi tidak sebagai var).

Arun Vijayraghavan

Arun Vijayraghavan
sumber