क्या 'var' का उपयोग प्रदर्शन को प्रभावित करेगा?


230

इससे पहले मैंने एक सवाल पूछा कि मैं इतने सारे उदाहरणों का उपयोग क्यों कर रहा हूं कि वे varकीवर्ड का उपयोग करें और जवाब मिला कि यह केवल गुमनाम प्रकारों के लिए आवश्यक है, फिर भी इसका उपयोग लेखन कोड को 'तेज' / आसान और 'सिर्फ इसलिए' बनाने के लिए किया जाता है।

इस लिंक के बाद ("C # 3.0 - Var Isn't Objec") मैंने देखा कि varआईएल में सही प्रकार से संकलित हो जाता है (आप इसे मिडवे डाउन लेख के बारे में देखेंगे)।

मेरा प्रश्न यह है कि यदि कोई भी, IL कोड varकीवर्ड टेक का उपयोग करता है , और क्या यह कोड के प्रदर्शन पर औसत दर्जे का स्तर होने के करीब भी होगा, अगर यह हर जगह उपयोग किया गया था?


1
प्रश्न का उत्तर युगों पहले दिया गया था, बस var के विरुद्ध एक और बात जोड़ना चाहता था - संकलन समय पर हल होने के बावजूद इसे Visual Studio के "फाइंड ऑल रिफरेंस" और रिसर्पर के "फाइंड यूजेज" द्वारा ठीक से नहीं देखा जा सकता है, यदि आप सभी प्रकार के उपयोग करना चाहते हैं - और यह तय नहीं होने वाला है क्योंकि यह बहुत धीमा होगा।
कोला नोव

varविजुअल स्टूडियो 2019 में " केओला वेरिएबल्स " के साथ निश्चित रूप से "फाइंड ऑल रिफरेंस" के साथ काम करने की घोषणा की गई है , इसलिए यदि यह कभी टूट गया तो इसे ठीक कर दिया गया है। लेकिन मैं इस बात की पुष्टि कर सकता हूं कि यह विजुअल स्टूडियो 2012 के रूप में वापस काम करता है, इसलिए मुझे यकीन नहीं है कि आपने दावा किया कि यह काम नहीं किया।
हेरोहार्ट

@Herohtar कोड "वर्ग X {} X GetX () {return new X ();} शून्य उपयोग () {var x = GetX ();}" और निम्नलिखित सभी संदर्भों को X, "var x = x x" के रूप में देखने का प्रयास करें। ) "बिट हाइलाइट नहीं किया गया है - नवीनतम VS2019 में अब तक, यही मेरा मतलब है। यह हाइलाइट किया जाता है, हालांकि यदि आप var
KolA के

1
@ कोलकाता, मैं देख रहा हूं कि आपका क्या मतलब है - जब आप "सभी संदर्भ खोजें" का उपयोग करते हैं तो varइसे संदर्भ नहीं माना जाएगा । दिलचस्प बात यह है कि अगर आप का उपयोग पर "सभी संदर्भ खोजें" कि बयान में, यह होगा आप के लिए संदर्भ दिखाने (हालांकि यह अभी भी सूचीबद्ध नहीं करेगा बयान)। इसके अतिरिक्त, जब कर्सर चालू होता है , तो यह एक ही दस्तावेज़ (और इसके विपरीत) के सभी उदाहरणों को उजागर करेगा । XXvarXvarvarX
हेरोहार्ट

जवाबों:


316

varकीवर्ड के लिए कोई अतिरिक्त IL कोड नहीं है : परिणामी IL गैर-अनाम प्रकारों के लिए समान होना चाहिए। यदि कंपाइलर उस IL को नहीं बना सकता है क्योंकि यह पता नहीं लगा सकता है कि आप किस प्रकार का उपयोग करना चाहते हैं, तो आपको एक कंपाइलर त्रुटि मिलेगी।

एकमात्र चाल यह है कि varएक सटीक प्रकार का अनुमान लगाया जाएगा जहां आपने एक इंटरफ़ेस या माता-पिता का प्रकार चुना होगा यदि आप मैन्युअल रूप से सेट करने के लिए थे।


8 साल बाद अपडेट करें

मुझे इसे अपडेट करने की आवश्यकता है क्योंकि मेरी समझ बदल गई है। अब मेरा मानना ​​है कि यह संभव हो सकता है varकि उस स्थिति में प्रदर्शन को प्रभावित करने के लिए जहां कोई विधि एक इंटरफ़ेस लौटाती है, लेकिन आपने एक सटीक प्रकार का उपयोग किया होगा। उदाहरण के लिए, यदि आपके पास यह विधि है:

IList<int> Foo()
{
    return Enumerable.Range(0,10).ToList();
}

विधि को कॉल करने के लिए कोड की इन तीन पंक्तियों पर विचार करें:

List<int> bar1 = Foo();
IList<int> bar = Foo();
var bar3 = Foo();

तीनों उम्मीद के मुताबिक संकलन और निष्पादन करते हैं। हालाँकि, पहली दो पंक्तियाँ बिल्कुल समान नहीं हैं, और तीसरी पंक्ति पहली के बजाय दूसरी से मेल खाएगी। क्योंकि के हस्ताक्षरFoo() वापस करना है IList<int>, यही कारण है कि कंपाइलर bar3चर का निर्माण करेगा ।

प्रदर्शन के दृष्टिकोण से, ज्यादातर आप नोटिस नहीं करेंगे। हालांकि, ऐसी परिस्थितियां हैं जहां तीसरी पंक्ति का प्रदर्शन पहले के प्रदर्शन के समान तेज नहीं हो सकता है । जैसा कि आप bar3चर का उपयोग करना जारी रखते हैं , हो सकता है कि कंपाइलर उसी तरीके से कॉल भेजने में सक्षम न हो।

ध्यान दें कि यह संभव है (संभावना भी) घबराना इस अंतर को मिटाने में सक्षम होगा, लेकिन इसकी गारंटी नहीं है। आम तौर पर, आपको अभी भी varप्रदर्शन के मामले में एक गैर-कारक होना चाहिए । यह निश्चित रूप से एक dynamicचर का उपयोग करना पसंद नहीं है । लेकिन कहने का मतलब यह है कि इससे फर्क नहीं पड़ सकता है।


23
इतना ही नहीं आईएल समान होना चाहिए - यह है समान। var i = 42; int i = 42 के समान कोड के लिए संकलित करता है;
ब्रायन रासमुसेन

15
@BrianRasmussen: मुझे पता है कि आपका पद पुराना है पुराना है, लेकिन मुझे लगता है var i = 42;(infers type int है) समान नहीं है long i = 42;। तो कुछ मामलों में आप अनुमान के प्रकार के बारे में गलत धारणा बना सकते हैं। यदि मूल्य फिट नहीं है, तो यह मायावी / बढ़त मामले में रनटाइम त्रुटियों का कारण बन सकता है। उस कारण से, यह तब भी एक अच्छा विचार हो सकता है जब मूल्य स्पष्ट नहीं होता है। उदाहरण के लिए, var x = new List<List<Dictionary<int, string>()>()>()स्वीकार्य होगा, लेकिन var x = 42कुछ अस्पष्ट है और इसे लिखा जाना चाहिए int x = 42। लेकिन प्रत्येक अपने स्वयं के लिए ...
नेल्सन रोथमेल

50
@ नेल्सन अभिभाषण: अस्पष्ट var x = 42; नहीं है। पूर्णांक शाब्दिक प्रकार के होते हैं int। यदि आप एक शाब्दिक लंबा लिखना चाहते हैं var x = 42L;
ब्रायन रासमुसेन

6
Uhm C # में IL के लिए क्या है? मैंने वास्तव में इसके बारे में कभी नहीं सुना।
०१:०t पर शुद्धटप

15
कोड की 3 लाइनों के आपके उदाहरण में जो पहली पंक्ति को अलग तरीके से व्यवहार करता है वह संकलन नहीं करता है । दूसरी और तीसरी पंक्ति, जो दोनों कर संकलन, बिल्कुल वही बात करते हैं। यदि Fooएक Listके बजाय एक वापस किया जाता है IList, तो सभी तीन लाइनें संकलित करेंगी लेकिन तीसरी पंक्ति पहली पंक्ति की तरह व्यवहार करेगी , दूसरी नहीं।
सेविती

72

जैसा कि जोएल कहते हैं, कंपाइलर कंपाइल-टाइम पर काम करता है कि किस प्रकार का संस्करण होना चाहिए, प्रभावी रूप से यह एक चाल है जो कंपाइलर कीस्ट्रोक्स को बचाने के लिए करता है, इसलिए उदाहरण के लिए

var s = "hi";

द्वारा प्रतिस्थापित किया जाता है

string s = "hi";

संकलक द्वारा किसी भी आईएल के उत्पन्न होने से पहले। उत्पन्न IL ठीक उसी तरह होगा जैसे आप स्ट्रिंग टाइप करते हैं।


26

जैसा कि किसी ने अभी तक रिफ्लेक्टर का उल्लेख नहीं किया है ...

यदि आप निम्नलिखित C # कोड संकलित करते हैं:

static void Main(string[] args)
{
    var x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

फिर उस पर रिफ्लेक्टर का उपयोग करें, आपको मिलता है:

// Methods
private static void Main(string[] args)
{
    string x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

तो जवाब स्पष्ट रूप से कोई रनटाइम प्रदर्शन हिट है!


17

निम्नलिखित विधि के लिए:

   private static void StringVsVarILOutput()
    {
        var string1 = new String(new char[9]);

        string string2 = new String(new char[9]);
    }

IL आउटपुट यह है:

        {
          .method private hidebysig static void  StringVsVarILOutput() cil managed
          // Code size       28 (0x1c)
          .maxstack  2
          .locals init ([0] string string1,
                   [1] string string2)
          IL_0000:  nop
          IL_0001:  ldc.i4.s   9
          IL_0003:  newarr     [mscorlib]System.Char
          IL_0008:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_000d:  stloc.0
          IL_000e:  ldc.i4.s   9
          IL_0010:  newarr     [mscorlib]System.Char
          IL_0015:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_001a:  stloc.1
          IL_001b:  ret
        } // end of method Program::StringVsVarILOutput

14

C # कंपाइलर सही varसमय पर वेरिएबल के सही प्रकार को संक्रमित करता है। उत्पन्न IL में कोई अंतर नहीं है।


14

तो, स्पष्ट होने के लिए, यह एक आलसी कोडिंग शैली है। मैं पसंद को देखते हुए, देशी प्रकार पसंद करता हूं; मैं यह सुनिश्चित करने के लिए "शोर" का अतिरिक्त हिस्सा ले लूंगा कि मैं कोड / डिबग समय में वही सोच रहा हूं जो मैं लिख रहा हूं और पढ़ रहा हूं। * श्रग *


1
प्रदर्शन के बारे में सवाल का जवाब और न ही आपके व्यक्तिपरक दृष्टिकोण। सही उत्तर यह है कि इसका प्रदर्शन पर कोई प्रभाव नहीं है। मैंने करीबी के लिए मतदान किया
एंडर्स

यह इस सवाल का जवाब नहीं देता है कि क्या varप्रदर्शन को प्रभावित करता है; आप सिर्फ इस बारे में अपनी राय बता रहे हैं कि लोगों को इसका उपयोग करना चाहिए या नहीं।
हेरोहट्टर

उदाहरण के लिए, बाद में मूल्य से टाइपिंग का संदर्भ, इंट 5 से स्विचिंग 5.25 पर स्विच करना, बिल्कुल प्रदर्शन मुद्दों का कारण बन सकता है। *
श्रग

नहीं, यह किसी भी प्रदर्शन के मुद्दों का कारण नहीं होगा; आपको किसी भी ऐसे स्थान पर त्रुटियाँ उत्पन्न हो जाएँगी जो किसी प्रकार के परिवर्तन की उम्मीद कर रहे थे intक्योंकि यह स्वचालित रूप से परिवर्तित नहीं हो सकता है float, लेकिन यह बिल्कुल वही है जो आपके द्वारा स्पष्ट रूप से उपयोग किए जाने intऔर फिर बदलने के लिए होता है float। किसी भी मामले में, आपका जवाब अभी भी " varप्रभावित प्रदर्शन का उपयोग करता है" के सवाल का जवाब नहीं देता है ? (विशेष रूप से उत्पन्न आईएल के संदर्भ में)
हेरोहार्ट

8

मुझे नहीं लगता कि आप ठीक से समझ पाए हैं कि आपने क्या पढ़ा है। यह सही प्रकार पर संकलित हो जाता है, फिर वहाँ है कोई फर्क नहीं। जब मैं ऐसा करता हूं:

var i = 42;

संकलक जानता है कि यह एक इंट है, और कोड उत्पन्न करता है जैसे कि मैंने लिखा था

int i = 42;

जैसा कि आप पोस्ट से कहते हैं, यह उसी प्रकार से संकलित हो जाता है । यह रनटाइम चेक या अतिरिक्त कोड की आवश्यकता के अलावा कुछ भी नहीं है। संकलक केवल यह पता लगाता है कि प्रकार क्या होना चाहिए, और इसका उपयोग करता है।


सही है, लेकिन क्या होगा अगर आप बाद में i = i - someVar और someVar = 3.3। मैं एक इंट, अब हूँ। यह स्पष्ट होना बेहतर है कि न केवल कंपाइलर को खामियां खोजने के लिए एक सिर शुरू करना है, बल्कि रनटाइम त्रुटियों या प्रक्रिया-धीमा प्रकार के रूपांतरणों को कम करना है। * श्रग * यह कोड को स्व-वर्णन के लिए भी बेहतर बनाता है। मैं यह लंबे समय से कर रहा हूं। मैं हर बार स्पष्ट प्रकार के साथ "शोर" कोड लूंगा, पसंद को देखते हुए।
क्रिस एचएच

5

Var का उपयोग करने के लिए कोई रनटाइम प्रदर्शन लागत नहीं है। हालांकि, मुझे संदेह है कि एक संकलित प्रदर्शन लागत होगी क्योंकि कंपाइलर को टाइप करने की आवश्यकता है, हालांकि यह सबसे अधिक संभावना नहीं होगी।


10
आरएचएस को अपने प्रकार की गणना किसी भी तरह से करनी होती है - कंपाइलर बेमेल प्रकारों को पकड़ता है और एक त्रुटि को फेंक देता है, इसलिए वास्तव में वहां कोई लागत नहीं है, मुझे लगता है।
जिमी

3

अगर कंपाइलर ऑटोमैटिक टाइप इनफेंसिंग कर सकता है, तो परफॉर्मेंस को लेकर कोई समस्या नहीं होगी। ये दोनों एक ही कोड जनरेट करेंगे

var    x = new ClassA();
ClassA x = new ClassA();

हालाँकि, यदि आप टाइप कर रहे हैं गतिशील रूप से (LINQ ...) तो varआपका एकमात्र प्रश्न है और यह कहने के लिए कि क्या जुर्माना है, यह तुलना करने के लिए अन्य तंत्र है।


3

मैं हमेशा वेब लेख या गाइड लेखन में शब्द संस्करण का उपयोग करता हूं।

ऑनलाइन लेख के पाठ संपादक की चौड़ाई छोटी है।

अगर मैं यह लिखूं:

SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

आप देखेंगे कि ऊपर दिया गया प्री कोड टेक्स्ट बहुत लंबा है और बॉक्स से बहता है, यह छिप जाता है। पूरा सिंटैक्स देखने के लिए पाठक को दाईं ओर स्क्रॉल करना होगा।

इसलिए मैं हमेशा वेब लेख लेखन में कीवर्ड संस्करण का उपयोग करता हूं।

var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

पूरे प्रदान किए गए प्री कोड केवल स्क्रीन के भीतर फिट होते हैं।

व्यवहार में, वस्तु घोषित करने के लिए, मैं शायद ही कभी var का उपयोग करता हूं, मैं वस्तु को तेजी से घोषित करने के लिए intellisense पर भरोसा करता हूं।

उदाहरण:

SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject();

लेकिन, किसी विधि से ऑब्जेक्ट को वापस करने के लिए, मैं कोड को तेजी से लिखने के लिए var का उपयोग करता हूं।

उदाहरण:

var coolObject = GetCoolObject(param1, param2);

यदि आप छात्रों के लिए लिख रहे हैं, तो अपने कुत्ते के भोजन को खाएं और इसे हमेशा "सही" तरीके से लिखें, लगातार। छात्र अक्सर चीजों को 100% शब्दशः और हृदय तक ले जाते हैं, और वे रास्ते में आने वाली किसी भी फूहड़ आदत का उपयोग करना शुरू कर देंगे। $ .02
क्रिस एचएच

1

"var" उन चीजों में से एक है जिन्हें लोग या तो प्यार करते हैं या नफरत करते हैं (जैसे क्षेत्र)। हालांकि, क्षेत्रों के विपरीत, अनाम कक्षाएं बनाते समय संस्करण बिल्कुल आवश्यक है।

मेरे लिए, जब आप सीधे किसी वस्तु को नया कर रहे हैं तो var का अर्थ है:

var dict = new Dictionary<string, string>();

कहा जा रहा है, आप आसानी से बस कर सकते हैं:

Dictionary<string, string> dict = नए और अंतर्मुखी आप के लिए यहाँ बाकी में भर जाएगा।

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

Resharper "var" का उपयोग करने के लिए सभी तरफ लगता है, जो अधिक लोगों को इस तरह से करने के लिए धक्का दे सकता है। लेकिन मैं इस बात से सहमत हूं कि यदि आप एक विधि को बुला रहे हैं तो यह पढ़ना कठिन है और यह स्पष्ट नहीं है कि नाम से क्या लौटाया जा रहा है।

var स्वयं किसी भी चीज़ को धीमा नहीं करता है, लेकिन इसके लिए एक चेतावनी है जिसके बारे में बहुत से लोग नहीं सोचते हैं। यदि आप करते हैं var result = SomeMethod();तो उसके बाद का कोड किसी प्रकार के परिणाम की उम्मीद कर रहा है जहां आप विभिन्न तरीकों या गुणों या जो भी कहेंगे। यदि SomeMethod()इसकी परिभाषा कुछ अन्य प्रकार में बदल जाती है, लेकिन यह अनुबंध से मिलता है, तो दूसरा कोड उम्मीद कर रहा था, आपने बस एक बहुत बुरा बग बनाया (यदि कोई इकाई / एकीकरण परीक्षण नहीं है, तो निश्चित रूप से)।


0

यह स्थिति का निर्भर करता है, यदि आप उपयोग करने की कोशिश करते हैं, तो यह कोड बोल्ड है।

अभिव्यक्ति "OBJECT" में बदल जाती है और प्रदर्शन में बहुत कमी आती है, लेकिन यह एक अलग समस्या है।

कोड:

public class Fruta
{
    dynamic _instance;

    public Fruta(dynamic obj)
    {
        _instance = obj;
    }

    public dynamic GetInstance()
    {
        return _instance;
    }
}

public class Manga
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
    public int MyProperty3 { get; set; }
}

public class Pera
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
}

public class Executa
{
    public string Exec(int count, int value)
    {
        int x = 0;
        Random random = new Random();
        Stopwatch time = new Stopwatch();
        time.Start();

        while (x < count)
        {
            if (value == 0)
            {
                var obj = new Pera();
            }
            else if (value == 1)
            {
                Pera obj = new Pera();
            }
            else if (value == 2)
            {
                var obj = new Banana();
            }
            else if (value == 3)
            {
                var obj = (0 == random.Next(0, 1) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance());
            }
            else
            {
                Banana obj = new Banana();
            }

            x++;
        }

        time.Stop();
        return time.Elapsed.ToString();
    }

    public void ExecManga()
    {
        var obj = new Fruta(new Manga()).GetInstance();
        Manga obj2 = obj;
    }

    public void ExecPera()
    {
        var obj = new Fruta(new Pera()).GetInstance();
        Pera obj2 = obj;
    }
}

ILSPY के साथ उपरोक्त परिणाम।

public string Exec(int count, int value)
{
    int x = 0;
    Random random = new Random();
    Stopwatch time = new Stopwatch();
    time.Start();

    for (; x < count; x++)
    {
        switch (value)
        {
            case 0:
                {
                    Pera obj5 = new Pera();
                    break;
                }
            case 1:
                {
                    Pera obj4 = new Pera();
                    break;
                }
            case 2:
                {
                    Banana obj3 = default(Banana);
                    break;
                }
            case 3:
                {
                    object obj2 = (random.Next(0, 1) == 0) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance();
                    break;
                }
            default:
                {
                    Banana obj = default(Banana);
                    break;
                }
        }
    }
time.Stop();
return time.Elapsed.ToString();
}

यदि आप चाहते हैं कि इस कोड का उपयोग कोड bellow करें, और समय का अंतर प्राप्त करें।

        static void Main(string[] args)
    {
        Executa exec = new Executa();            
        int x = 0;
        int times = 4;
        int count = 100000000;
        int[] intanceType = new int[4] { 0, 1, 2, 3 };

        while(x < times)
        {                
            Parallel.For(0, intanceType.Length, (i) => {
                Console.WriteLine($"Tentativa:{x} Tipo de Instancia: {intanceType[i]} Tempo Execução: {exec.Exec(count, intanceType[i])}");
            });
            x++;
        }

        Console.ReadLine();
    }

सादर

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