c# - कॉन्स्ट और रीडोनली के बीच क्या अंतर है?




.net const (20)

const और readonly बीच क्या अंतर है और क्या आप दूसरे पर एक का उपयोग करते हैं?


स्थिरांक

  • स्थिरांक डिफ़ॉल्ट रूप से स्थिर हैं
  • उनके पास संकलन-समय पर एक मूल्य होना चाहिए (आप उदाहरण के लिए 3.14 * 2 हो सकते हैं, लेकिन विधियों को कॉल नहीं कर सकते हैं)
  • कार्यों के भीतर घोषित किया जा सकता है
  • उन सभी असेंबली में प्रतिलिपि बनाई जाती है जो उनका उपयोग करती हैं (प्रत्येक असेंबली को मूल्यों की स्थानीय प्रति प्राप्त होती है)
  • विशेषताओं में इस्तेमाल किया जा सकता है

केवल उदाहरण फ़ील्ड

  • कन्स्ट्रक्टर निकलने के समय निर्धारित मूल्य होना चाहिए
  • उदाहरण बनने पर मूल्यांकन किया जाता है

स्टेटिक रीडोनली फ़ील्ड

  • मूल्यांकन किया जाता है जब कोड निष्पादन कक्षा संदर्भ हिट करता है (जब नया उदाहरण बनाया जाता है या एक स्थिर विधि निष्पादित की जाती है)
  • स्थिर कन्स्ट्रक्टर के समय तक मूल्यांकन मूल्य होना चाहिए
  • इन पर थ्रेडस्टैटिक एट्रिब्यूट डालने की अनुशंसा नहीं की जाती है (स्थैतिक रचनाकार केवल एक धागे में निष्पादित किए जाएंगे और इसके धागे के लिए मान निर्धारित करेंगे; अन्य सभी धागे में यह मान अनियमित हो जाएगा)

अंतर यह है कि एक स्थैतिक रीडोनली फ़ील्ड का मान रन टाइम पर सेट होता है, इसलिए प्रोग्राम के विभिन्न निष्पादन के लिए इसका अलग-अलग मूल्य हो सकता है। हालांकि, एक कॉन्स फ़ील्ड का मान संकलन समय स्थिर पर सेट होता है।

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

विवरण के लिए, कृपया इस विषय पर सी # अक्सर पूछे जाने वाले प्रश्न देखें: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx


एक और गोचा

चूंकि कॉन्स्ट वास्तव में केवल मूल डेटा प्रकारों के साथ काम करता है, यदि आप कक्षा के साथ काम करना चाहते हैं, तो आप रीडऑनली का उपयोग करने के लिए "मजबूर" महसूस कर सकते हैं। हालांकि, जाल से सावधान रहें! केवल पढ़ने का मतलब है कि आप ऑब्जेक्ट को किसी अन्य ऑब्जेक्ट से प्रतिस्थापित नहीं कर सकते हैं (आप इसे किसी अन्य ऑब्जेक्ट को नहीं देख सकते हैं)। लेकिन किसी भी प्रक्रिया जिसमें ऑब्जेक्ट का संदर्भ है, ऑब्जेक्ट के अंदर मानों को संशोधित करने के लिए स्वतंत्र है!

इसलिए सोचने में भ्रमित न हों कि केवल पढ़ने का मतलब है कि कोई उपयोगकर्ता चीजों को नहीं बदल सकता है। किसी वर्ग के तत्कालता को आंतरिक मूल्यों को बदलने से रोकने के लिए सी # में कोई सरल वाक्यविन्यास नहीं है (जहां तक ​​मुझे पता है)।


एक कॉन्स एक संकलन-समय स्थिर होता है जबकि पाठक एक मूल्य को रन-टाइम पर गणना करने और कन्स्ट्रक्टर या फील्ड प्रारंभकर्ता में सेट करने की अनुमति देता है। तो, एक 'कॉन्स' हमेशा स्थिर रहता है लेकिन 'रीडोनली' केवल एक बार असाइन किए जाने के बाद ही पढ़ा जाता है।

सी # टीम के एरिक लिपर्ट में विभिन्न प्रकार की अपरिवर्तनीयता पर अधिक जानकारी है


एक निरंतर उपभोक्ता में एक शाब्दिक मूल्य के रूप में संकलित किया जाएगा जबकि स्थैतिक स्ट्रिंग परिभाषित मूल्य के संदर्भ के रूप में कार्य करेगा।

एक अभ्यास के रूप में, बाहरी पुस्तकालय बनाने का प्रयास करें और इसे कंसोल एप्लिकेशन में उपभोग करें, फिर लाइब्रेरी में मानों को बदलें और इसे पुन: संकलित करें (उपभोक्ता प्रोग्राम को पुन: संकलित किए बिना), डीएलएल को निर्देशिका में छोड़ दें और EXE मैन्युअल रूप से चलाएं, आपको ढूंढना चाहिए कि निरंतर स्ट्रिंग नहीं बदलती है।


के स्पष्ट अंतर के अलावा

  • एक const वीएस के लिए परिभाषा के समय मूल्य घोषित करने के लिए पाठकों को गतिशील रूप से गणना की जा सकती है लेकिन कन्स्ट्रक्टर से पहले असाइन करने की आवश्यकता है .. उसके बाद यह जमे हुए है।
  • 'कॉन्स स्पष्ट रूप से static । आप उन्हें एक्सेस करने के लिए ClassName.ConstantName नोटेशन का उपयोग करते हैं।

एक सूक्ष्म अंतर है। AssemblyA ए में परिभाषित कक्षा पर विचार करें।

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyB बी AssemblyA AssemblyB संदर्भित करता है और कोड में इन मानों का उपयोग करता है। जब यह संकलित किया जाता है,

  • const वैल्यू के मामले में, यह एक खोज-प्रतिस्थापन की तरह है, मूल्य 2 को ' AssemblyB ' में 'बेक किया गया' है। इसका मतलब है कि अगर कल मैं भविष्य में I_CONST_VALUE को 20 में अपडेट कर I_CONST_VALUEअसेंबलीबी में तब तक 2 होगा जब तक मैं इसे पुन: संकलित नहीं करता
  • readonly मूल्य के मामले में, यह एक स्मृति स्थान के लिए एक ref तरह है। मूल्य AssemblyB के आईएल में बेक नहीं है। इसका अर्थ यह है कि यदि स्मृति स्थान अपडेट किया गया है, तो AssemblyB को बिना किसी संकलन के नए मान मिलते हैं। इसलिए यदि I_RO_VALUE को 30 तक अपडेट किया गया है, तो आपको केवल I_RO_VALUE बनाने की आवश्यकता है। सभी ग्राहकों को पुन: संकलित करने की आवश्यकता नहीं है।

तो यदि आप आश्वस्त हैं कि निरंतर का मूल्य एक const उपयोग नहीं करेगा।

public const int CM_IN_A_METER = 100;

लेकिन यदि आपके पास स्थिरता है जो बदल सकता है (उदा। सटीक) .. या जब संदेह में, readonly उपयोग करें।

public readonly float PI = 3.14;

अपडेट करें: अकु को एक उल्लेख प्राप्त करने की जरूरत है, उसने पहले इसे इंगित किया। इसके अलावा मुझे यह प्लग करना होगा जहां मैंने यह सीखा .. प्रभावी सी # - बिल वैगनर


केवल पढ़ने के साथ एक छोटा गोचाचा है। एक पाठक क्षेत्र को कन्स्ट्रक्टर के भीतर कई बार सेट किया जा सकता है। भले ही मूल्य दो अलग-अलग जंजीर रचनाकारों में सेट किया गया हो, फिर भी इसकी अनुमति है।


public class Sample {
    private readonly string ro;

    public Sample() {
        ro = "set";
    }

    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}

कॉन्स और रीडोनली समान हैं, लेकिन वे बिल्कुल वही नहीं हैं। एक कॉन्स फील्ड एक संकलन-समय निरंतर है, जिसका अर्थ है कि उस मान को संकलन-समय पर गणना की जा सकती है। एक पठनीय क्षेत्र अतिरिक्त परिदृश्यों को सक्षम बनाता है जिसमें प्रकार के निर्माण के दौरान कुछ कोड चलाना चाहिए। निर्माण के बाद, एक पठनीय क्षेत्र को बदला नहीं जा सकता है।

उदाहरण के लिए, सदस्यों को परिभाषित करने के लिए कॉन्स सदस्यों का उपयोग किया जा सकता है:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

चूंकि 3.14 और 0 जैसे मान संकलन-समय स्थिरांक हैं। हालांकि, उस मामले पर विचार करें जहां आप एक प्रकार को परिभाषित करते हैं और इसके कुछ प्री-फैब उदाहरण प्रदान करना चाहते हैं। उदाहरण के लिए, आप कलर क्लास को परिभाषित करना और ब्लैक, व्हाइट इत्यादि जैसे सामान्य रंगों के लिए "स्थिरांक" प्रदान करना चाहते हैं। यह कॉन्स सदस्यों के साथ ऐसा करना संभव नहीं है, क्योंकि दाएं हाथ के पक्ष संकलित-समय स्थिरांक नहीं हैं। कोई नियमित स्थिर सदस्यों के साथ ऐसा कर सकता है:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

लेकिन फिर काले रंग के सफेद और सफेद मूल्यों को स्वैप करके, रंग के क्लाइंट को इसके साथ मिलकर रखने के लिए कुछ भी नहीं है। कहने की जरूरत नहीं है, इससे कलर क्लास के अन्य ग्राहकों के लिए कर्कश हो जाएगा। "रीडोनली" सुविधा इस परिदृश्य को संबोधित करती है। घोषणाओं में केवल पढ़ने वाले कीवर्ड को पेश करके, हम क्लाइंट कोड को चारों ओर घूमने से रोकने के दौरान लचीली प्रारंभिकता को संरक्षित करते हैं।

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

यह ध्यान रखना दिलचस्प है कि कॉन्स सदस्य हमेशा स्थिर होते हैं, जबकि एक पाठक सदस्य नियमित क्षेत्र की तरह स्थिर या नहीं हो सकता है।

इन दो उद्देश्यों के लिए एक ही कीवर्ड का उपयोग करना संभव है, लेकिन इससे या तो संस्करण की समस्याएं या प्रदर्शन समस्याएं होती हैं। एक पल के लिए मान लें कि हमने इस (कॉन्स) के लिए एक ही कीवर्ड का उपयोग किया और एक डेवलपर ने लिखा:

public class A
{
    public static const C = 0;
}

और एक अलग डेवलपर ने कोड लिखा जो ए पर निर्भर था:

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

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


निरंतर चर घोषित और संकलित समय पर शुरू किया गया है। वार्ड के बाद मूल्य बदला नहीं जा सकता है। केवल-पढ़ने योग्य चर कक्षा के स्टेटिक कन्स्ट्रक्टर से ही शुरू किए जाएंगे। केवल तभी उपयोग किया जाता है जब हम रन टाइम पर मान असाइन करना चाहते हैं।


परिवर्तनीय चिह्नित चर वैरिएबल टाइप किए गए मैक्रोज़ की तुलना में थोड़ा अधिक हैं, संकलन समय कॉन्स्ट चर संदर्भों में इनलाइन शाब्दिक मानों के साथ प्रतिस्थापित किया गया है। नतीजतन केवल कुछ अंतर्निहित आदिम मूल्य प्रकारों का उपयोग इस तरह किया जा सकता है। पठनीय रूप से चिह्नित वैरिएबल को एक कन्स्ट्रक्टर में रन-टाइम पर सेट किया जा सकता है और उनके पढ़ने-केवल-नास को रन-टाइम के दौरान भी लागू किया जाता है। इसके साथ जुड़े कुछ मामूली प्रदर्शन लागत हैं लेकिन इसका मतलब है कि आप किसी भी प्रकार (यहां तक ​​कि संदर्भ प्रकार) के साथ केवल पढ़ने के लिए उपयोग कर सकते हैं।

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


बस जोड़ने के लिए, संदर्भ प्रकारों के लिए केवल पढ़ने के लिए संदर्भ केवल संदर्भों को संदर्भित नहीं करता है। उदाहरण के लिए:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

मुख्यतः; आप रनटाइम पर एक गैर-निरंतर मान पर एक स्थैतिक रीडोनली फ़ील्ड को मान निर्दिष्ट कर सकते हैं, जबकि एक कॉन्स को निरंतर मान असाइन किया जाना चाहिए।


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

public static readonly uint l1 = (uint) DateTime.Now.Ticks;

लोगों ने जो कहा है उसे जोड़ने के लिए एक चीज। यदि आपके पास एक रीडोनली वैल्यू (जैसे रीडोनली मैक्सफूकाउंट = 4;) है, तो आप उस वैल्यू को बदल सकते हैं जो असेंबली को एक अलग मूल्य के साथ उस असेंबली का एक नया संस्करण भेजकर देखता है (उदाहरण के लिए मैक्सफूकाउंट = 5;)

लेकिन एक कॉन्स के साथ, कॉलर संकलित होने पर इसे कॉलर के कोड में जोड़ा जाएगा।

यदि आप सी # प्रवीणता के इस स्तर तक पहुंच गए हैं, तो आप बिल वाग्नेर की पुस्तक, प्रभावी सी #: 50 के लिए तैयार हैं, अपने सी # में सुधार करने के लिए विशिष्ट तरीके, जो इस प्रश्न का विस्तार से विस्तार करते हैं, (और 49 अन्य चीजें)।


सी # नेट में कॉन्स और रीडोनली फ़ील्ड्स के बीच उल्लेखनीय अंतर है

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

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

केवल पढ़ने के लिए स्थैतिक घोषित किया जा सकता है, लेकिन आवश्यक नहीं है। घोषणा के समय शुरू करने की जरूरत नहीं है। इसका मूल्य कन्स्ट्रक्टर का उपयोग करके असाइन या बदला जा सकता है। इसलिए, यह उदाहरण देता है जब इंस्टेंस क्लास सदस्य के रूप में उपयोग किया जाता है। दो अलग-अलग तत्कालता में केवल पढ़ने के क्षेत्र का अलग-अलग मूल्य हो सकता है। पूर्व के लिए -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

फिर रीडोनली फ़ील्ड को तत्काल विशिष्ट मानों के साथ प्रारंभ किया जा सकता है, जैसा कि निम्नानुसार है:

A objOne = new A(5);
A objTwo = new A(10);

यहां, उदाहरण objOne के पास रीडोनली फ़ील्ड का मान 5 के रूप में होगा और objTwo में 10 है। जो कॉन्स्ट का उपयोग करके संभव नहीं है।


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

public class MyClass
{
    public const double PI1 = 3.14159;
}

एक readonly सदस्य निरंतर की तरह है कि यह एक अपरिवर्तनीय मूल्य का प्रतिनिधित्व करता है। अंतर यह है कि एक readonly सदस्य को रनटाइम पर एक कन्स्ट्रक्टर में प्रारंभ किया जा सकता है, साथ ही उन्हें घोषित किए जाने के रूप में प्रारंभ करने में सक्षम किया जा सकता है।

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

स्थिरांक

  • उन्हें static घोषित नहीं किया जा सकता है (वे स्पष्ट रूप से स्थैतिक हैं)
  • संकलन समय पर निरंतर मूल्य का मूल्यांकन किया जाता है
  • स्थिरांक केवल घोषणा में शुरू किया जाता है

सिफ़ पढ़िये

  • वे या तो उदाहरण-स्तर या स्थैतिक हो सकते हैं
  • रन रन पर मूल्य का मूल्यांकन किया जाता है
  • पाठक को घोषणा में या कन्स्ट्रक्टर में कोड द्वारा प्रारंभ किया जा सकता है

यह बताता है । सारांश: घोषणा समय पर कॉन्स को प्रारंभ किया जाना चाहिए, केवल रचनाकार पर प्रारंभ किया जा सकता है (और इस प्रकार इस्तेमाल किए गए कन्स्ट्रक्टर के आधार पर एक अलग मूल्य है)।

संपादित करें: सूक्ष्म अंतर के लिए ऊपर गिशू गॉचा देखें


यहां एक और लिंक दिखाया गया है कि कैसे कॉन्स्टेंस संस्करण सुरक्षित नहीं है, या संदर्भ प्रकारों के लिए प्रासंगिक है।

सारांश :

  • आपकी कॉन्स प्रॉपर्टी का मान संकलन समय पर सेट है और रनटाइम पर नहीं बदला जा सकता है
  • कॉन्स्ट को स्थैतिक के रूप में चिह्नित नहीं किया जा सकता है - कीवर्ड इंगित करता है कि वे स्थिर हैं, जो पढ़े जाने वाले फ़ील्ड के विपरीत हो सकते हैं।
  • मूल्य (आदिम) प्रकार को छोड़कर कॉन्स्ट कुछ भी नहीं हो सकता है
  • पाठक कीवर्ड फ़ील्ड को अपरिवर्तनीय के रूप में चिह्नित करता है। हालांकि संपत्ति के वर्ग के अंदर संपत्ति बदल दी जा सकती है
  • केवल पढ़ने वाले कीवर्ड को स्थैतिक के साथ जोड़ा जा सकता है ताकि इसे एक कॉन्स (सतह पर कम से कम) के रूप में कार्य किया जा सके। जब आप दोनों के बीच आईएल देखते हैं तो एक महत्वपूर्ण अंतर होता है
  • आईएस में कॉन्स फ़ील्ड को "शाब्दिक" के रूप में चिह्नित किया जाता है जबकि पढ़ा जाता है "initonly"

केवल पढ़ने के लिए : रनटाइम पर सीटीआर के माध्यम से मूल्य बदला जा सकता है। लेकिन सदस्य समारोह के माध्यम से नहीं

निरंतर : स्थिर अपमान से। मूल्य कहीं से भी बदला नहीं जा सकता है (सीटीओआर, फंक्शन, रनटाइम इत्यादि कहीं नहीं)


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

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;






readonly