2009-06-26 19 views
5

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

public IEnumerable<T> Foo(ref int valueThatMeansSomething) 
{ 
    // Stuff 

    yield return ...; 
} 

यह मुझे नेट करता है "त्रुटि 476 Iterators को रेफरी या आउट पैरामीटर नहीं हो सकता है"।

मुझे यह पूर्णांक मानरेटर में संशोधित करने और पुनरावर्तक के कॉलर द्वारा उपयोग करने योग्य करने की आवश्यकता है। दूसरे शब्दों में, Foo() जो भी कॉल करता है, उसे valueThatMeansSomething और Foo() का अंतिम मान जानना चाहता है। असल में, मैं एक पूर्णांक चाहता हूं जो एक संदर्भ प्रकार है जो मूल्य प्रकार नहीं है।

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

public class ValueWrapper<T> 
    where T : struct 
{ 
    public ValueWrapper(T item) 
    { 
     this.Item = item; 
    } 

    public T Item { get; set; } 
} 

तो:

ValueWrapper<int> w = new ValueWrapper<int>(0); 
foreach(T item in Foo(w)) 
{ 
    // Do stuff 
} 

if (w.Item < 0) { /* Do stuff */ } 

वहाँ किसी भी वर्ग या तंत्र बीसीएल में पहले से ही इस संभाल करने के लिए है? ऊपर प्रस्तावित ValueWrapper<T> के साथ कोई भी दोष?

उत्तर

4

नहीं, मैं बहुत आश्वस्त हूं (मेरे वास्तविक उपयोग तो मेरे foreach पाश कि Foo() कॉल अंदर चर से निपटने ऊपर के उदाहरण से अधिक जटिल है एक विकल्प। अवधि। है नहीं) में मौजूदा कुछ भी नहीं है बीसीएल जो यह कर सकता है। आपका सबसे अच्छा विकल्प ठीक है जो आपने प्रस्तावित किया है। ValueWrapper के कार्यान्वयन को वास्तव में आपके द्वारा प्रस्तावित किए गए प्रस्तावों की तुलना में अधिक जटिल नहीं होना चाहिए।

बेशक, यह थ्रेड-सुरक्षित होने की गारंटी नहीं है, लेकिन अगर आपको इसकी आवश्यकता है तो आप स्वचालित संपत्ति को बैकिंग वैरिएबल के साथ मानक में परिवर्तित कर सकते हैं और फ़ील्ड को volatile के रूप में चिह्नित कर सकते हैं (बीमा को बीमा करने के लिए बीमा- हर समय आज तक)।

+2

फ़ील्ड अस्थिर बनाना थ्रेड सुरक्षा सुनिश्चित करने के लिए पर्याप्त नहीं है क्योंकि मनमानी मूल्य प्रकारों को लिखना सी # विनिर्देश द्वारा परमाणु होने की गारंटी नहीं है। अस्थिरता परमाणुता की गारंटी नहीं देता है, यह केवल कुछ संकलक-अनुकूलन-प्रेरित आदेश मुद्दों को समाप्त करता है। –

+0

यदि आप थ्रेड सुरक्षा की परवाह करते हैं, तो ताले का उपयोग करें। –

+0

@Eric: हाँ, अच्छा बिंदु। मैंने मूल रूप से लिखा था कि यह परमाणुता की गारंटी देता है, लेकिन फिर इसे तुरंत हटा दिया गया क्योंकि मुझे एहसास हुआ कि यह आवश्यक नहीं है। – Noldorin

5

आप केवल मूल्य लिखने के लिए की जरूरत है फिर एक और तकनीक होगा:

public IEnumerable<whatever> Foo(Action<int> setter) { ... } 

int value = 0; 
foreach(var x in Foo(x => {value=x;}) { ... } 

संयोगवश, मैं कारण वहाँ अपने ब्लॉग में iterator ब्लॉक पर इतने सारे नासमझ प्रतिबंध नहीं है पर एक श्रृंखला कर रही हो जाएगा जुलाई में। "कोई रेफरी पैरामीटर क्यों नहीं?" श्रृंखला में जल्दी होगा।

http://blogs.msdn.com/ericlippert/archive/tags/Iterators/default.aspx

0

मैं लंबे समय से सोचा कि बीसीएल वास्तव में निम्नलिखित की तरह एक वर्ग और इंटरफ़ेस कुछ है चाहिए:

 
public delegate void ActByRef<T1,T2>(ref T1 p1); 
public delegate void ActByRefRef<T1,T2>(ref T1 p1, ref T2 p2); 
public interface IReadWriteActUpon<T> 
{ 
    T Value {get; set;} 
    void ActUpon(ActByRef<T> proc); 
    void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, 
          ref TExtraparam ExtraParam); 
} 

public sealed class MutableWrapper<T> : IReadWrite<T> 
{ 
    public T Value; 
    public MutableWrapper(T value) { this.Value = value; } 
    T IReadWriteActUpon<T>.Value {get {return this.Value;} set {this.Value = value;} } 
    public void ActUpon(ActByRef<T> proc) 
    { 
    proc(ref Value); 
    } 
    public void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, 
          ref TExtraparam ExtraParam) 
    { 
    proc(ref Value, ref ExtraParam); 
    } 
} 

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

इंटरफ़ेस शामिल किया गया है नहीं एक MutableWrapper<T> के बहुत से उपयोगकर्ताओं इंटरफेस का उपयोग करने के बजाय, बल्कि इसलिए कि एक IReadWriteActUpon<T> स्थितियों, जिनमें से कुछ कैप्सूलीकरण करना पड़ेगा की एक किस्म में उपयोगी हो सकता है चाहेगा क्योंकि, और कोई है जो एक उदाहरण है MutableWrapper<T> का कोड उस कोड को पास करना चाहेगा जो IReadWriteActUpon<T> इंटरफ़ेस में encapsulated डेटा के साथ काम करने के लिए डिज़ाइन किया गया है।

संबंधित मुद्दे