जवाबों:
हां, लेकिन आपको इसके readonly
बजाय इसे घोषित करने की आवश्यकता है const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
कारण यह है कि const
केवल उसी फ़ील्ड पर लागू किया जा सकता है जिसका मूल्य संकलन-समय पर जाना जाता है। आपके द्वारा दिखाया गया सरणी आरंभीकरण C # में एक स्थिर अभिव्यक्ति नहीं है, इसलिए यह एक संकलक त्रुटि पैदा करता है।
यह घोषित करना readonly
उस समस्या को हल करता है क्योंकि मूल्य को रन-टाइम तक आरंभीकृत नहीं किया जाता है (हालांकि यह पहली बार शुरू होने की गारंटी है कि सरणी का उपयोग किया जाता है)।
यह इस बात पर निर्भर करता है कि आप आखिरकार क्या हासिल करना चाहते हैं, आप एक एनम की घोषणा करने पर भी विचार कर सकते हैं:
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
अनुरोधित शब्दार्थ का कोई सदृश होना आवश्यक है।
static
लिए इसे काम करने की आवश्यकता नहीं है, यह सिर्फ Titles
उदाहरण के बिना संदर्भ की संभावना को जोड़ता है , लेकिन विभिन्न उदाहरणों के लिए मूल्य बदलने की संभावना को दूर करता है (उदाहरण के लिए आप पैरामीटर के साथ निर्माता हो सकते हैं, जिसके आधार पर आप उस readonly
फ़ील्ड के मूल्य को बदल सकते हैं )।
आप सरणी को घोषित कर सकते हैं readonly
, लेकिन ध्यान रखें कि आप readonly
सरणी के तत्व को बदल सकते हैं ।
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
कोम द्वारा सुझाए गए, या IList के रूप में, एनम का उपयोग करने पर विचार करें।
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
नहीं है readonly
...
आप एक 'कॉन्स्ट' एरे नहीं बना सकते क्योंकि एरे ऑब्जेक्ट्स हैं और केवल रनटाइम पर बनाए जा सकते हैं और कॉन्सटेबल इकाइयाँ संकलन समय पर हल हो जाती हैं।
इसके बजाय आप क्या कर सकते हैं अपने सरणी को "आसानी से" घोषित करें। यह उसी तरह का प्रभाव है जैसा कि कॉन्स्टिट को छोड़कर रनटाइम पर सेट किया जा सकता है। यह केवल एक बार ही सेट किया जा सकता है और इसके बाद एक पठनीय (यानी कास्ट) मान है।
const int[] a = null;
जो बहुत उपयोगी नहीं है, लेकिन वास्तव में एक सरणी का एक उदाहरण है।
C # 6 के बाद से आप इसे लिख सकते हैं:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
इन्हें भी देखें: C #: द न्यू एंड इम्प्रूव्ड C # 6.0 (विशेषकर अध्याय "एक्सप्रेशन बोडिड फंक्शंस एंड प्रॉपर्टीज़")
यह केवल-पढ़ने के लिए स्थिर संपत्ति बना देगा, लेकिन यह अभी भी आपको दी गई सरणी की सामग्री को बदलने की अनुमति देगा, लेकिन जब आप संपत्ति को फिर से कॉल करते हैं, तो आपको फिर से मूल, अनलेल्ड सरणी मिल जाएगी।
स्पष्टीकरण के लिए, यह कोड समान है (या वास्तव में इसके लिए एक आशुलिपि):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
कृपया ध्यान दें कि इस दृष्टिकोण के लिए एक नकारात्मक पहलू है: एक नया सरणी वास्तव में प्रत्येक और हर संदर्भ पर त्वरित है, इसलिए यदि आप बहुत बड़े सरणी का उपयोग कर रहे हैं, तो यह सबसे कुशल समाधान नहीं हो सकता है। लेकिन यदि आप उसी सरणी का उपयोग करते हैं (उदाहरण के लिए एक निजी विशेषता में डालकर) तो यह फिर से सरणी की सामग्री को बदलने की संभावना को खोल देगा।
यदि आप एक अपरिवर्तनीय सरणी (या सूची) रखना चाहते हैं, तो आप इसका उपयोग भी कर सकते हैं:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
लेकिन, इसमें अभी भी परिवर्तनों का जोखिम है, क्योंकि आप अभी भी इसे एक स्ट्रिंग में वापस डाल सकते हैं [और सामग्री को बदल सकते हैं, जैसे कि:
((string[]) Titles)[1] = "French";
Titles[0]
उदाहरण के लिए , यदि आप असाइन करते हैं तो आपको एक संकलन त्रुटि नहीं मिलेगी - वास्तव में, असाइनमेंट प्रयास को चुपचाप अनदेखा कर दिया जाता है। हर बार सरणी को फिर से बनाने की अक्षमता के साथ संयुक्त, मुझे आश्चर्य है कि क्या यह दृष्टिकोण भी दिखाने योग्य है। इसके विपरीत, दूसरा दृष्टिकोण कुशल है, और आपको अपरिवर्तनीयता को हराने के लिए अपने रास्ते से बाहर जाना होगा।
यदि आप IReadOnlyList इंटरफ़ेस के पीछे एक सरणी घोषित करते हैं, तो आपको निरंतर मान के साथ एक निरंतर सरणी मिलती है जो रनटाइम पर घोषित की जाती है:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
.NET 4.5 और उच्चतर में उपलब्ध है।
एक .NET फ्रेमवर्क v4.5 + समाधान जो tdbeckett के उत्तर में सुधार करता है :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
नोट: यह देखते हुए कि संग्रह वैचारिक रूप से स्थिर है, वर्ग स्तर static
पर इसे घोषित करने के लिए इसे बनाने के लिए समझ में आ सकता है।
उपरोक्त:
सरणी के साथ एक बार संपत्ति के अंतर्निहित बैकिंग क्षेत्र को आरम्भ करता है।
ध्यान दें { get; }
- अर्थात, केवल एक संपत्ति पाने वाला घोषित करना - वह है जो संपत्ति को केवल अनुमानित रूप से केवल-पढ़ने के लिए बनाता है ( वास्तव में एक सिंटैक्स त्रुटि के readonly
साथ संयोजन करने की कोशिश कर रहा है { get; }
)।
वैकल्पिक रूप से, आप सिर्फ छोड़ सकते हैं { get; }
और एक संपत्ति के बजाय readonly
एक फ़ील्ड बनाने के लिए जोड़ सकते हैं, जैसा कि सवाल है, लेकिन सार्वजनिक डेटा सदस्यों को फ़ील्ड के बजाय गुणों के रूप में उजागर करना एक अच्छी आदत है।
एक सरणी बनाता है- संरचना की तरह ( अनुक्रमणित पहुंच की अनुमति देता है ) जो वास्तव में और मजबूत रूप से केवल पढ़ने योग्य है (वैचारिक रूप से स्थिर, एक बार बनाया गया), दोनों सम्मान के साथ:
IReadOnlyList<T>
समाधान है, जहां एक (string[])
डाली तत्वों के लिए लेखन पहुँच हासिल करने के लिए इस्तेमाल किया जा सकता है, के रूप में दिखाया गया है mjepsen के मददगार जवाब । IReadOnlyCollection<T>
ReadOnlyCollection
IReadOnlyCollection
अनुक्रमित पहुंच का समर्थन नहीं करता है, इसलिए इसका उपयोग यहां नहीं किया जा सकता है। इसके अतिरिक्त, जैसे IReadOnlyList
(जिसमें अनुक्रमणित पहुंच है) यह वापस जोड़कर तत्व हेरफेर करने के लिए अतिसंवेदनशील है string[]
। दूसरे शब्दों में: ReadOnlyCollection
(जो आप एक स्ट्रिंग सरणी नहीं कर सकते हैं) सबसे मजबूत समाधान है। एक गेटर का उपयोग नहीं करना एक विकल्प है (और मैंने उस नोट का जवाब अपडेट किया है), लेकिन सार्वजनिक डेटा के साथ संपत्ति के साथ रहना बेहतर है।
मेरी जरूरतों के लिए, मैं static
असंभव के बजाय सरणी को परिभाषित करता हूं const
और यह काम करता है:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
ओपी उदाहरण से हटाना भी काम करता है, लेकिन यह (या आपका जवाब) दोनों को बदलने की अनुमति देता है: Titles
उदाहरण और कोई भी मूल्य। तो इस उत्तर में क्या बात है?
readonly
आप एक अलग तरीका अपना सकते हैं: अपने सरणी का प्रतिनिधित्व करने के लिए एक निरंतर स्ट्रिंग को परिभाषित करें और फिर आवश्यकता पड़ने पर स्ट्रिंग को एक सरणी में विभाजित करें, जैसे
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
यह दृष्टिकोण आपको एक निरंतरता देता है जिसे कॉन्फ़िगरेशन में संग्रहीत किया जा सकता है और जरूरत पड़ने पर एक सरणी में परिवर्तित किया जा सकता है।
पूर्णता के लिए, अब हमारे पास अपने निपटान में ImmutableArrays भी है। यह वास्तव में अपरिवर्तनीय होना चाहिए:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
System.Collections.Immutable NuGet संदर्भ की आवश्यकता है
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
यह वह तरीका है जो आप करना चाहते हैं:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
यह बहुत आसानी से एक सरणी के समान है।
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; यदि आप इसे वैसे भी ReadOnlyCollection बनाते हैं, तो प्रत्येक पुनर्प्राप्ति पर सूची को फिर से बनाने की आवश्यकता नहीं है।
यह एकमात्र सही उत्तर है। आप वर्तमान में ऐसा नहीं कर सकते।
अन्य सभी उत्तर स्थिर रीड-ओनली चर का उपयोग करने का सुझाव दे रहे हैं जो समान हैं , लेकिन स्थिर के समान नहीं हैं। असेंबली में एक निरंतर हार्ड कोडित होता है। एक स्थिर रीड ओनली वेरिएबल एक बार सेटल हो जाता है, शायद जैसा कि किसी ऑब्जेक्ट को इनिशियलाइज़ किया जाता है।
ये कभी-कभी विनिमेय होते हैं, लेकिन हमेशा नहीं।
एक विकल्प के रूप में, एक आसानी से सरणी के साथ तत्वों-के-संशोधित-संशोधित मुद्दे के आसपास पाने के लिए, आप इसके बजाय एक स्थिर संपत्ति का उपयोग कर सकते हैं। (व्यक्तिगत तत्वों को अभी भी बदला जा सकता है, लेकिन ये परिवर्तन केवल सरणी की स्थानीय प्रति पर किए जाएंगे।)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
बेशक, यह विशेष रूप से कुशल नहीं होगा क्योंकि हर बार एक नया स्ट्रिंग सरणी बनाया जाता है।
सबसे अच्छा विकल्प:
public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };