डायनामिक (C # 4) और var में क्या अंतर है?


199

मैंने उस नए कीवर्ड के बारे में एक टन लेख पढ़ा था जो C # v4 के साथ शिपिंग है, लेकिन मैं "डायनामिक" और "var" के बीच अंतर नहीं कर सका।

इस लेख ने मुझे इसके बारे में सोचने पर मजबूर किया, लेकिन मैं अभी भी कोई अंतर नहीं देख सकता।

क्या यह है कि आप "var" का उपयोग केवल स्थानीय चर के रूप में कर सकते हैं, लेकिन स्थानीय और वैश्विक दोनों के रूप में गतिशील?

क्या आप डायनामिक कीवर्ड के बिना कुछ कोड दिखा सकते हैं और फिर डायनामिक कीवर्ड के साथ समान कोड दिखा सकते हैं?

जवाबों:


455

varस्थैतिक टाइप किया गया है - संकलक और रनटाइम प्रकार जानते हैं - वे बस आपको कुछ टाइपिंग बचाते हैं ... निम्नलिखित 100% समान हैं:

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

तथा

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

जो कुछ भी हुआ वह यह था कि संकलक को पता चला कि sएक स्ट्रिंग होना चाहिए (शुरुआती से)। दोनों मामलों में, यह जानता है (आईएल में) जिसका s.Lengthअर्थ है (उदाहरण) string.Lengthसंपत्ति।

dynamicएक बहुत अलग जानवर है; यह सबसे अधिक समान है object, लेकिन गतिशील प्रेषण के साथ:

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

यहाँ, डायनामिकs टाइप किया गया है । इसके बारे में पता नहीं है string.Length, क्योंकि यह संकलन के समय के बारे में कुछ भी नहीं जानता हैs । उदाहरण के लिए, निम्नलिखित संकलन (लेकिन नहीं चलाया जाएगा):

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

क्रम (केवल) में, यह होगा की जांच के लिए FlibbleBananaSnowballसंपत्ति - यह पता लगाने के लिए असफल, और स्पार्क्स की बौछार में विस्फोट।

साथ dynamic, गुण / तरीकों / ऑपरेटरों / आदि हल कर रहे हैं क्रम में वास्तविक वस्तु पर आधारित है,। COM से बात करने के लिए बहुत आसान (जिसमें रनटाइम-केवल गुण हो सकते हैं), DLR, या अन्य गतिशील सिस्टम, जैसे javascript


3
एक दिलचस्प सवाल यह होगा कि क्या सांख्यिकीय रूप से घोषित वर्गों के गतिशील पूर्वज हैं। उदाहरण: कक्षा X {सार्वजनिक int Y {प्राप्त; सेट;}} गतिशील (X) s = GetSpecialX (); स्ट्रिंग परीक्षण कॉल करना = sY; कंपाइलर त्रुटि उत्पन्न करेगा क्योंकि कंपाइलर Y के बारे में जानता है लेकिन string test2 = sZ ठीक संकलित करेगा और रन-टाइम पर जांचा जाएगा। मैं ऐसे आधे गतिशील वर्गों के बहुत मूल्य के बारे में सोच सकता था!
mmmmmmmm

@rstevens - IIRC, आप एक इंटरफ़ेस के माध्यम से गतिशील व्यवहार जोड़ सकते हैं (हालांकि C # में गतिशील प्रकारों को लागू करने के लिए कोई प्रत्यक्ष भाषा समर्थन नहीं है - केवल उनका उपभोग करना), इसलिए यह अवास्तविक नहीं है ... ओह हम जो मज़ा कर सकते हैं; - पी
मार्क Gravell

हालांकि यह ध्यान रखना महत्वपूर्ण है कि कभी-कभी varऐसे प्रकारों का अनुमान लगा सकते हैं जो उप-जातियों और निहित जातियों के कारण वांछित नहीं हो सकते हैं। अर्थात्, varएक प्रकार के अनुमान से अलग प्रकार का हल हो सकता है जब अंतर्निहित जातियाँ होती हैं (सबसे विशेष रूप से एक अधिक सामान्य प्रकार के लिए, लेकिन यह इस तक सीमित नहीं है)। एक तुच्छ उदाहरण object x = ""बनाम var x = ""बनाम है var x = "" as object, लेकिन अन्य अधिक डरपोक (और यथार्थवादी) मामले हो सकते हैं और सूक्ष्म कीड़े पैदा कर सकते हैं।

मार्क के अच्छे उदाहरण के बारे में विस्तार से बताने के लिए, पहले मामले में (स्थैतिक प्रकार के साथ), कंपाइलर जानता है कि कॉल करने केWriteLine लिए कई ओवरलोड में से कौन सा है । यह "बाध्यकारी" संकलन-समय होता है। के साथ मामले में dynamic, का प्रकार भी .Lengthहोना dynamicचाहिए, और यह रन-टाइम तक यह तय नहीं होता है कि कौन सा ओवरलोड (यदि कोई हो) WriteLineसबसे अच्छा फिट बैठता है। बाइंडिंग रन-टाइम होती है।
जेपी स्टिग नील्सन

4
जब आप varविज़ुअल स्टूडियो में कीवर्ड मँडराते हैं, तो वास्तविक प्रकार प्रदर्शित होता है जिसे अनुमान लगाया जा रहा है। आपको दिखाता है कि प्रकार संकलन समय पर जाना जाता है।
ईसाई फ्रेड

56

Var के साथ घोषित चर अनुमानित रूप से लेकिन सांख्यिकीय रूप से टाइप किए जाते हैं। गतिशील के साथ घोषित चर गतिशील रूप से टाइप किए जाते हैं। रूबी और पायथन जैसी गतिशील भाषाओं का समर्थन करने के लिए सीएलआर में इस क्षमता को जोड़ा गया था।

मुझे यह जोड़ना चाहिए कि इसका मतलब है कि गतिशील घोषणाएं रन-टाइम पर हल की जाती हैं, संकलन समय पर var घोषणाओं को हल किया जाता है।


42

मैं गतिशील और var के बीच अंतर समझाने जा रहा हूँ ।

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

यह काम करेगा। संकलक गतिशील चर के प्रकार को फिर से बना सकता है ।
पहले यह पूर्णांक के रूप में टाइप बनाता है और उसके बाद कंपाइलर स्ट्रिंग के रूप में टाइप करेगा
लेकिन 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 


' Var ' कीवर्ड का उपयोग करते समय, कंपाइलर समय पर टाइप करने वाले द्वारा तय किया जाता है, जबकि ' डायनामिक ' कीवर्ड का उपयोग करते समय, टाइप रनटाइम द्वारा तय किया जाता है।
' var ' कीवर्ड, एक दृढ़ता से अंतर्निहित रूप से टाइप किया गया स्थानीय वैरिएबल जिसके लिए कंपाइलर इनिशियलाइज़ेशन एक्सप्रेशन से टाइप को निर्धारित करने में सक्षम है - LINQ प्रोग्रामिंग करते समय बहुत उपयोगी है।
कंपाइलर को डायनेमिक प्रकार के वैरिएबल के बारे में कोई जानकारी नहीं है । इसलिए कंपाइलर कोई बुद्धिमत्ता नहीं दिखाएगा।
संकलक में var प्रकार के संचित मूल्य के बारे में सभी जानकारी होती है इसलिए संकलक बुद्धिमत्ता दिखाएगा।
गतिशील प्रकार समारोह तर्क और समारोह के रूप में पारित कर दिया जा सकता है भी ऑब्जेक्ट प्रकार लौट सकते हैं
लेकिन
वर प्रकार समारोह तर्क और समारोह वापस नहीं लौट सकते ऑब्जेक्ट प्रकार के रूप में पारित नहीं किया जा सकता। इस प्रकार का चर उस दायरे में काम कर सकता है जहां इसे परिभाषित किया गया है।


14

var का अर्थ है कि स्थैतिक प्रकार की जाँच (प्रारंभिक बाध्यकारी) लागू होती है। डायनामिक का अर्थ है कि डायनेमिक प्रकार की जाँच (देर से बाध्यकारी) लागू किया जाता है। कोड के संदर्भ में, निम्नलिखित को सम्मिलित करें:

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

यदि आप इसे संकलित करते हैं और ILSpy के साथ परिणामों का निरीक्षण करते हैं, तो आप पाएंगे कि कंपाइलर ने कुछ देर से बाध्यकारी कोड जोड़ा है जो b से हैलो () को कॉल को हैंडल करेगा, जबकि becuase को जल्दी बाइंडिंग लागू किया गया था, एक हैलो को कॉल करने में सक्षम है () सीधे।

उदाहरण के लिए (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);
        }
    }
}

अंतर की खोज करने के लिए आप जो सबसे अच्छी चीज कर सकते हैं वह यह है कि अपने आप को इस तरह से थोड़ा कंसोल ऐप लिखें, और खुद को ILSpy के साथ परीक्षण करें।


महान मूल उदाहरण कैसे IL संकलन के बाद दोनों का इलाज करता है। धन्यवाद।
किंग्स

12

एक बड़ा अंतर - आपके पास एक गतिशील रिटर्न प्रकार हो सकता है।

dynamic Foo(int x)
{
    dynamic result;

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

    return result;
}

10

यहाँ सरल उदाहरण है जो डायनामिक (4.0) और वार के बीच अंतर प्रदर्शित करता है

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.

शिव ममदी


2
मेरी धारणा यह है कि **कोड उदाहरण में वर्णों की उपस्थिति केवल जोर को इंगित करने के लिए है और वास्तविक कार्य कोड का हिस्सा बनने का इरादा नहीं है।
डेविड आरआर

7

var एक सामान्य प्रकार की घोषणा के लिए सिर्फ एक आशुलिपि है, जहां आप संकलक को सही प्रकार का अनुमान लगाने देते हैं।

dynamic एक नया (स्थिर) प्रकार है, जहां सभी चेक रनटाइम पर किए जाते हैं, संकलक द्वारा नहीं।


4

वेरिएबल के साथ घोषित चर का प्रकार कंपाइलर द्वारा निर्धारित किया जाता है, यह प्रकार के नाम को निर्दिष्ट करने के लिए एक शॉर्टकट है, इससे अधिक कुछ नहीं।

हालाँकि गतिशील को रनटाइम पर निर्धारित किया जाता है, संकलक को वास्तविक प्रकार का कोई पता नहीं है, और उस चर के साथ सभी विधि / फ़ील्ड / संपत्ति एक्सेस रनटाइम पर काम करेगी।


3

यह एक अच्छा यूट्यूब वीडियो है जो व्यावहारिक प्रदर्शन के साथ varवीएस के बारे में बात करता है Dynamic

नीचे स्नैपशॉट के साथ एक अधिक विस्तृत विवरण दिया गया है।

वार को जल्दी बाँधा जाता है (स्टेटिकली चेक किया गया) जबकि डायनामिक को देर से बाइंड किया जाता है (डायनामिकली असेसमेंट)।

Var कीवर्ड आपके दाएँ हाथ के डेटा को देखता है और फिर संकलन समय के दौरान यह बाएँ हाथ के डेटा प्रकार को तय करता है। दूसरे शब्दों में var कीवर्ड आपको बहुत सी चीज़ों को टाइप करने से बचाता है। नीचे दी गई छवि पर एक नज़र डालें, जब हमने स्ट्रिंग डेटा दिया है और x चर मेरे टूल टिप में स्ट्रिंग डेटा प्रकार दिखाता है।

यहां छवि विवरण दर्ज करें

दूसरी ओर डायनामिक कीवर्ड पूरी तरह से अलग उद्देश्य के लिए है। गतिशील वस्तुओं का मूल्यांकन रनटाइम के दौरान किया जाता है। उदाहरण के लिए नीचे दिए गए कोड में "लंबाई" संपत्ति मौजूद है या नहीं, इसका मूल्यांकन रनटाइम के दौरान किया जाता है। मैंने जानबूझकर एक छोटा "एल" टाइप किया है, इसलिए यह कार्यक्रम ठीक संकलित किया गया, लेकिन जब वास्तव में इसे निष्पादित किया गया तो "लंबाई" संपत्ति में एक त्रुटि हुई कहा जाता था (SMALL "l")।

यहां छवि विवरण दर्ज करें


2

डायनेमिक वेरिएबल और वेरिएबल वैरिएबल दोनों किसी भी प्रकार के मूल्य को स्टोर कर सकते हैं लेकिन घोषणा के समय 'var' को इनिशियलाइज़ करना आवश्यक है।

कंपाइलर को 'डायनामिक' वेरिएबल के प्रकार के बारे में कोई जानकारी नहीं है। var संकलक सुरक्षित है अर्थात संकलक में संग्रहीत मूल्य के बारे में सभी जानकारी होती है, जिससे यह रन-टाइम पर कोई समस्या उत्पन्न नहीं करता है।

डायनामिक प्रकार को फ़ंक्शन तर्क के रूप में पारित किया जा सकता है और फ़ंक्शन भी इसे वापस कर सकता है। Var प्रकार को फ़ंक्शन तर्क के रूप में पारित नहीं किया जा सकता है और फ़ंक्शन ऑब्जेक्ट प्रकार को वापस नहीं कर सकता है। इस प्रकार का चर उस दायरे में काम कर सकता है जहां इसे परिभाषित किया गया है।

डायनेमिक कास्टिंग के मामले में आवश्यकता नहीं है, लेकिन आपको संग्रहित प्रकार से संबंधित संपत्ति और विधियों को जानना होगा, जबकि var के लिए कोई कास्ट करने की आवश्यकता नहीं है क्योंकि संकलक के पास ऑपरेशन करने के लिए सभी जानकारी है।

डायनामिक: रिफ्लेक्शन या डायनेमिक लैंग्वेज सपोर्ट या COM ऑब्जेक्ट के साथ कोडिंग करते समय उपयोगी है, क्योंकि हमें कम मात्रा में कोड लिखना होता है।

var: लिनेक प्रश्नों के परिणाम प्राप्त करते समय उपयोगी। 3.5 फ्रेमवर्क में यह लाइनक फीचर को सपोर्ट करने के लिए पेश किया गया है।

संदर्भ: Counsellingbyabhi


2
  1. वार और डायनामिक डिफाइन टाइप।
  2. var संकलन समय पर जबकि गतिशील रन समय पर हैं।
  3. वैर डिक्लेरेशन और इनिशियलाइज़ेशन में दोनों ही लगातार वेरिएबल की तरह अनिवार्य हैं
  4. डायनामिक इनिशियलाइज़ेशन में रीडऑनली वेरिएबल्स की तरह रन टाइम हो सकता है।
  5. var प्रकार में जो भी समय आरम्भ में तय किया जाता है वह अगली बार नहीं बदल सकता है
  6. गतिशील किसी भी प्रकार को अपना सकते हैं यहां तक ​​कि उपयोगकर्ता डेटाटाइप भी परिभाषित करते हैं।

1

गतिशील और var को भ्रमित न करें। संस्करण का उपयोग करते हुए एक स्थानीय चर की घोषणा करना एक सिंटैक्टिकल शॉर्टकट है जिसमें संकलक एक अभिव्यक्ति से विशिष्ट डेटा प्रकार का अनुमान लगाता है। वैर कीवर्ड का उपयोग केवल स्थानीय वेरिएबल्स को एक विधि के अंदर घोषित करने के लिए किया जा सकता है, जबकि डायनामिक कीवर्ड का उपयोग स्थानीय चर, फ़ील्ड और तर्क के लिए किया जा सकता है। आप एक्सप्रेशन के लिए एक्सप्रेशन नहीं डाल सकते हैं, लेकिन आप एक्सप्रेशन को डायनामिक कर सकते हैं। जब आप डायनामिक के साथ घोषित किए गए वैरिएबल को इनिशियलाइज़ करने की जरूरत नहीं है, तो आपको स्पष्ट रूप से वेरिएबल घोषित वेरिएबल को इनिशियलाइज़ करना होगा।


1
  1. Var (इंप्लिकेटेड टाइप्ड लोकल वेरिएबल) कीवर्ड का इस्तेमाल लोकल वेरिएबल्स को डिफाइन करने के लिए किया जाता है। Var के मामले में, अंतर्निहित डेटा टाइप को प्रारंभिक असाइनमेंट के आधार पर ही कंपाइल टाइम पर निर्धारित किया जाता है। शुरुआती असाइनमेंट को Var टाइप के साथ बनाया गया है, फिर यह दृढ़ता से टाइप हो जाएगा। यदि आप Var प्रकार के साथ किसी भी असंगत मूल्य को संग्रहीत करने का प्रयास करते हैं, तो इसका परिणाम संकलन समय त्रुटि के रूप में होगा।

उदाहरण:

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.

लेकिन डायनामिक प्रकार में, अंतर्निहित प्रकार केवल रन टाइम पर निर्धारित किया जाता है। डायनेमिक डेटा प्रकार को संकलन समय पर चेक नहीं किया जाता है और यह भी दृढ़ता से टाइप नहीं किया जाता है। हम डायनामिक प्रकार के लिए कोई भी प्रारंभिक मान असाइन कर सकते हैं और फिर इसे किसी भी नए पर पुनः असाइन किया जा सकता है अपने जीवन काल के दौरान मूल्य।

उदाहरण:

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]

यह IntelliSense सपोर्ट भी प्रदान नहीं करता है। जब हम linq के साथ भी काम देते हैं तो यह बेहतर सपोर्ट नहीं देता है। लेकिन क्या यह लैम्ब्डा एक्सप्रेशन, एक्सटेंशन के तरीके और अनाम तरीकों का समर्थन नहीं करता है।


1

यहाँ अंतर हैं

  • var स्टेटिक रूप से टाइप किया गया है (संकलन समय), डायनामिक डायनामिक टाइप (रन टाइम) है

  • वेरिएबल के रूप में घोषित एक वेरिएबल केवल स्थानीय रूप से इस्तेमाल किया जा सकता है, डायनामिक वेरिएबल्स को फ़ंक्शन के रूप में पारित किया जा सकता है (फ़ंक्शन सिग्नेचर एक परम को डायनामिक नहीं बल्कि वैर के रूप में परिभाषित कर सकता है)।

  • डायनामिक के साथ गुणों का रिज़ॉल्यूशन रनटाइम पर होता है और ऐसा वैसा नहीं होता है, जिसका अर्थ यह है कि संकलन के समय कोई भी वैरिएबल घोषित किया जा सकता है क्योंकि डायनेमिक एक ऐसी विधि कह सकता है, जो मौजूद हो सकती है या नहीं और इसलिए कंपाइलर कोई त्रुटि नहीं करेगा।

  • प्रकार के साथ कास्टिंग संभव नहीं है, लेकिन गतिशील के साथ संभव है (आप एक वस्तु को गतिशील के रूप में डाल सकते हैं लेकिन var के रूप में नहीं)।

अरुण विजयराघवन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.