दिलचस्प पोस्ट
एसवीएन में पुनरीक्षण बनाम संशोधनों की श्रेणी में विलय के बीच अंतर क्या है? एक आलसी मूल्यांकन चैंबर बताएं गलत डेटा प्रकार इनपुट को कैसे संभालना है एक माता पिता वादा के भीतर से वादे की एक सरणी हल क्या तेज़ है? CSS3 संक्रमण या jQuery एनिमेशन? प्रोग्रामेटिक रूप से बदलते टेक्स्टबॉक्स मान द्वारा जावास्क्रिप्ट ऑन-अप ईवेंट को कॉल करें Regex तक लेकिन इसमें शामिल नहीं कैसे नए आदेश को हटाने के लिए बास कमांड प्रतिस्थापन से बचें? फ़ायरफ़ॉक्स संगतता मैट्रिक्स के लिए एक निश्चित सेलेनियम वेबड्राइवर कहां मिल सकता हूं? AngularJS: ऊँचाई परिवर्तन के लिए देखने का बेहतर तरीका Android एप्लिकेशन पर लॉग इन करने के लिए Google- खाता का उपयोग करना I आईओएस में सीजीआईमेज आरफ कैसे रिलीज कर सकता हूं मैं MySQL का उपयोग कर दो तिथियों के बीच कैसे क्वेरी करूं? क्या मैं स्क्रॉल वीआईएल को प्रोग्राम में एंड्रॉइड स्क्रॉल कर सकता हूं? IPhone में XSLT का संस्करण

क्या एक संपत्ति को केवल सी # में स्थापित करने का एक तरीका है

मैं सी # ऑब्जेक्ट में संपत्ति को केवल एक बार सेट करने की अनुमति देने के लिए एक मार्ग की तलाश कर रहा हूँ ऐसा करने के लिए कोड लिखना आसान है, लेकिन यदि कोई मौजूद है तो मैं एक मानक तंत्र का उपयोग करना चाहता हूं।

 सार्वजनिक OneShot <int> SetOnceProperty {get;  सेट;  }

मुझे क्या करना है, यह है कि संपत्ति को सेट किया जा सकता है, अगर वह पहले से ही सेट नहीं है, लेकिन एक अपवाद फेंक दें अगर इसे पहले सेट किया गया है यह एक नल योग्य मूल्य की तरह कार्य करना चाहिए जहां मैं यह देख सकता हूं कि यह निर्धारित किया गया है या नहीं।

Solutions Collecting From Web of "क्या एक संपत्ति को केवल सी # में स्थापित करने का एक तरीका है"

इसके लिए टीपीएल में .NET 4.0 में सीधा समर्थन है; जब तक तब तक खुद को चेक न करें … यह कई पंक्तियां नहीं है, जो मुझे याद है …

कुछ इस तरह:

public sealed class WriteOnce<T> { private T value; private bool hasValue; public override string ToString() { return hasValue ? Convert.ToString(value) : ""; } public T Value { get { if (!hasValue) throw new InvalidOperationException("Value not set"); return value; } set { if (hasValue) throw new InvalidOperationException("Value already set"); this.value = value; this.hasValue = true; } } public T ValueOrDefault { get { return value; } } public static implicit operator T(WriteOnce<T> value) { return value.Value; } } 

फिर उपयोग करें, उदाहरण के लिए:

 readonly WriteOnce<string> name = new WriteOnce<string>(); public WriteOnce<string> Name { get { return name; } } 

आप अपना स्वयं रोल कर सकते हैं (अधिक मजबूत कार्यान्वयन के लिए जवाब का अंत देखें जो धागा सुरक्षित है और डिफ़ॉल्ट मानों का समर्थन करता है)।

 public class SetOnce<T> { private bool set; private T value; public T Value { get { return value; } set { if (set) throw new AlreadySetException(value); set = true; this.value = value; } } public static implicit operator T(SetOnce<T> toConvert) { return toConvert.value; } } 

आप इसे इस तरह उपयोग कर सकते हैं:

 public class Foo { private readonly SetOnce<int> toBeSetOnce = new SetOnce<int>(); public int ToBeSetOnce { get { return toBeSetOnce; } set { toBeSetOnce.Value = value; } } } 

नीचे अधिक मजबूत कार्यान्वयन

 public class SetOnce<T> { private readonly object syncLock = new object(); private readonly bool throwIfNotSet; private readonly string valueName; private bool set; private T value; public SetOnce(string valueName) { this.valueName = valueName; throwIfGet = true; } public SetOnce(string valueName, T defaultValue) { this.valueName = valueName; value = defaultValue; } public T Value { get { lock (syncLock) { if (!set && throwIfNotSet) throw new ValueNotSetException(valueName); return value; } } set { lock (syncLock) { if (set) throw new AlreadySetException(valueName, value); set = true; this.value = value; } } } public static implicit operator T(SetOnce<T> toConvert) { return toConvert.value; } } public class NamedValueException : InvalidOperationException { private readonly string valueName; public NamedValueException(string valueName, string messageFormat) : base(string.Format(messageFormat, valueName)) { this.valueName = valueName; } public string ValueName { get { return valueName; } } } public class AlreadySetException : NamedValueException { private const string MESSAGE = "The value \"{0}\" has already been set."; public AlreadySetException(string valueName) : base(valueName, MESSAGE) { } } public class ValueNotSetException : NamedValueException { private const string MESSAGE = "The value \"{0}\" has not yet been set."; public ValueNotSetException(string valueName) : base(valueName, MESSAGE) { } } 

यह झंडा के साथ नगण्य के साथ भी किया जा सकता है:

 private OneShot<int> setOnce; private bool setOnceSet; public OneShot<int> SetOnce { get { return setOnce; } set { if(setOnceSet) throw new InvalidOperationException(); setOnce = value; setOnceSet = true; } } 

जो अच्छा नहीं है क्योंकि आप संभावित रूप से रन-टाइम त्रुटि प्राप्त कर सकते हैं संकलन समय पर इस व्यवहार को लागू करने के लिए बेहतर है:

 public class Foo { private readonly OneShot<int> setOnce; public OneShot<int> SetOnce { get { return setOnce; } } public Foo() : this(null) { } public Foo(OneShot<int> setOnce) { this.setOnce = setOnce; } 

}

और फिर या तो निर्माता का उपयोग करें

जैसा कि मार्क ने कहा था कि यह डिफ़ॉल्ट रूप से नेट में करने का कोई रास्ता नहीं है। लेकिन एक को जोड़ना बहुत कठिन नहीं है

 public class SetOnceValue<T> { private T m_value; private bool m_isSet; public bool IsSet { get { return m_isSet; }} public T Value { get { if ( !IsSet ) { throw new InvalidOperationException("Value not set"); } return m_value; } public T ValueOrDefault { get { return m_isSet ? m_value : default(T); }} public SetOnceValue() { } public void SetValue(T value) { if ( IsSet ) { throw new InvalidOperationException("Already set"); } m_value = value; m_isSet = true; } } 

तब आप इसे अपने विशेष संपत्ति के समर्थन के रूप में उपयोग कर सकते हैं।

सी # में कोई ऐसी सुविधा नहीं है (3.5 के रूप में) आपको अपने आप को कोड करना होगा

क्या आपने केवल पढ़ने के लिए विचार किया है? http://en.csharp-online.net/const,_static_and_readonly

यह केवल init के दौरान सेट करने के लिए उपलब्ध है, लेकिन हो सकता है कि आप क्या चाहते हैं।

 /// <summary> /// Wrapper for once inizialization /// </summary> public class WriteOnce<T> { private T _value; private Int32 _hasValue; public T Value { get { return _value; } set { if (Interlocked.CompareExchange(ref _hasValue, 1, 0) == 0) _value = value; else throw new Exception(String.Format("You can't inizialize class instance {0} twice", typeof(WriteOnce<T>))); } } public WriteOnce(T defaultValue) { _value = defaultValue; } public static implicit operator T(WriteOnce<T> value) { return value.Value; } } 

इस पर मेरी यह बात है:

 public class ReadOnly<T> // or WriteOnce<T> or whatever name floats your boat { private readonly TaskCompletionSource<T> _tcs = new TaskCompletionSource<T>(); public Task<T> ValueAsync => _tcs.Task; public T Value => _tcs.Task.Result; public bool TrySetInitialValue(T value) { try { _tcs.SetResult(value); return true; } catch (InvalidOperationException) { return false; } } public void SetInitialValue(T value) { if (!TrySetInitialValue(value)) throw new InvalidOperationException("The value has already been set."); } public static implicit operator T(ReadOnly<T> readOnly) => readOnly.Value; public static implicit operator Task<T>(ReadOnly<T> readOnly) => readOnly.ValueAsync; } 

मार्क का जवाब यह सुझाव देता है कि टीपीएल इस कार्यक्षमता को प्रदान करता है और मुझे लगता है कि TaskCompletionSource<T> उसका मतलब हो सकता था, लेकिन मुझे यकीन नहीं हो सकता।

मेरे समाधान के कुछ अच्छे गुण:

  • TaskCompletionSource<T> एक आधिकारिक तौर पर समर्थन एमएस वर्ग है जो कार्यान्वयन को सरल करता है
  • आप सिंक्रोनस या अतुल्यकालिक रूप से मूल्य प्राप्त कर सकते हैं।
  • इस श्रेणी का एक उदाहरण निहित मूल्य के प्रकार को परिवर्तित करेगा जो इसे स्टोर करता है। जब आपके पास चारों ओर का मूल्य पार करने की आवश्यकता होती है, तो यह आपके कोड को थोड़ी-थोड़ी साफ कर सकता है

आप यह कर सकते हैं लेकिन एक स्पष्ट समाधान नहीं है और कोड पठनीयता सर्वश्रेष्ठ नहीं है। यदि आप कोड डिज़ाइन कर रहे हैं तो आप सेटर्स को रोकने के लिए एओपी के साथ मिलकर सिंगलटन प्राप्ति को देख सकते हैं। प्राप्ति सिर्फ 123 है

 interface IFoo { int Bar { get; } } class Foo : IFoo { public int Bar { get; set; } } class Program { public static void Main() { IFoo myFoo = new Foo() { Bar = 5 // valid }; int five = myFoo.Bar; // valid myFoo.Bar = 6; // compilation error } } 

सूचना है कि मायफू को IFoo के रूप में घोषित किया गया है, लेकिन फ़ू के रूप में तत्काल।

इसका मतलब है कि बार को प्रारंभिक ब्लॉक के भीतर सेट किया जा सकता है, लेकिन बाद में संदर्भ के माध्यम से myFoo नहीं।

जवाब यह मानते हैं कि भविष्य में किसी ऑब्जेक्ट के संदर्भ प्राप्त करने वाली ऑब्जेक्ट इसे बदलने की कोशिश नहीं करेंगे। यदि आप इस से रक्षा करना चाहते हैं, तो आपको अपना लिखना-एक बार कोड बनाने की ज़रूरत है, एक बार कोड केवल उन प्रकारों के लिए काम करता है जो आईसीएलओएनएबल या प्राथमिकताएं लागू करते हैं। उदाहरण के लिए स्ट्रिंग टाइप ICloneable लागू करता है तो आप डेटा के क्लोन या वास्तविक डेटा के बजाय आदिम के नए उदाहरण को वापस करेंगे।

केवल प्राथमिकताओं के लिए जेनरिक: टी GetObject जहां T: struct;

यह आवश्यक नहीं है अगर आप जानते हैं कि डेटा के संदर्भ प्राप्त करने वाले ऑब्जेक्ट इसे कभी भी अधिलेखित नहीं करेंगे।

इसके अलावा, विचार करें कि क्या ReadOnlyCollection आपके आवेदन के लिए काम करेगा। एक अपवाद तब भी फेंका जाता है जब भी डेटा पर परिवर्तन का प्रयास किया जाता है।