2009-11-21 15 views
9

मुझे आश्चर्य है अगर वहाँ इस तरह किसी भी तरह से कुछ मूल्य प्रकार के लिए संभव हो जाएगा ...दिलचस्प "रेफरी के पैरा" सुविधा, कोई कामकाज?

public static class ExtensionMethods { 
    public static void SetTo(this Boolean source, params Boolean[] bools) { 
     for (int i = 0; i < bools.Length; i++) { 
      bools[i] = source; 
     } 
    } 
} 

तो यह संभव होगा:

Boolean a = true, b, c = true, d = true, e; 
b.SetTo(a, c, d, e); 
बेशक

, इस वजह bools काम नहीं करता है एक मान प्रकार हैं ताकि वे फ़ंक्शन में एक मान के रूप में पारित हो जाएं, संदर्भ के रूप में नहीं।

मूल्य प्रकारों को संदर्भ प्रकारों (दूसरे वर्ग बनाकर) में लपेटने के अलावा, पैराम संशोधक का उपयोग करते समय संदर्भ (रेफरी) द्वारा फ़ंक्शन में चर को पार करने का कोई तरीका है?

उत्तर

19

यह संभव नहीं है। क्यों की व्याख्या करने के लिए, पहले क्यों यह है कि हम उन्हें ढेर पर रख कर मान प्रकार की स्थानीय चर का आवंटन रद्द करने का अनुकूलन पर अपने निबंध पढ़ें:

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

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

लेकिन चलो इस बारे में थोड़ा गहरा सोचें। यदि आप चाहते हैं कि "चीज जो मुझे एक चर सेट करने की अनुमति देती है" पास हो, तो हमारे पास है जो है। यह सिर्फ एक प्रतिनिधि है:

static void DoStuff<T>(this T thing, params Action<T>[] actions) 
{ 
    foreach(var action in actions) action(thing); 
} 
... 
bool b = whatever; 
b.DoStuff(x=>{q = x;}, x=>{r = x;}); 

समझ में आता है?

+0

"एक चर सेट करने की बात" एक बंद होने की तरह दिखती है, जो वैरिएबल को क्लास फ़ील्ड में बदल देती है। ऐसा लगता है कि एक विशेष प्रकार का भंडारण स्थान "कॉन्स रेफ टू ब्लॉब होल्डिंग एन कॉन्स्ट बायफ्रेज़ और एम गैर-कॉन्स बायफ्स" का प्रतिनिधित्व करता है, और फ़ंक्शन पैरामीटर के अलावा किसी भी उद्देश्य के लिए उस प्रकार के स्टोरेज स्थानों को उपयोग करने की अनुमति नहीं देनी चाहिए, सुरक्षित। ऐसे उद्देश्यों के लिए बंद करने का उपयोग करना लगता है। मेरे दिमाग में, उनके दायरे के बाहर चर का उपयोग करना आम तौर पर गलत है; बंद करने के लिए चर को घुमाने के बजाय, उन्हें गुजरने के दायरे-सीमित साधनों का उपयोग करना बेहतर होगा। – supercat

+0

जो मैं देखना चाहता हूं वह एक विशेष "ByRefDelegate" होगा जो एक स्थाई संग्रह के साथ एक स्थिर विधि सूचक को जोड़ देगा; ऐसी चीज को जारी नहीं किया जा सका - केवल घोंसला दिनचर्या में ही पारित किया जा सकता है। वे विधियां जो एक प्रतिनिधि को स्वीकार करती हैं लेकिन जारी नहीं रहती हैं, उन्हें "ByRefDelegates" को स्वीकार करने के अधिभार हो सकते हैं, और लागू होने पर संकलक बंद होने की बजाए उनको उत्पन्न कर सकते हैं, इस प्रकार आम मामले के लिए एक बड़ा प्रदर्शन बढ़ावा प्रदान करते हैं। – supercat

0

यह संभव नहीं होगा यदि bool एस संदर्भ प्रकार थे। जबकि एक class एक संदर्भ प्रकार है, Boolean[] में चर अभी भी एक मूल्य है यह है कि अभी मूल्य एक संदर्भ है। संदर्भ के मान को असाइन करना केवल उस विशेष चर के मान को बदलता है। ref चर की एक सरणी की अवधारणा समझ में नहीं आती है (जैसे कि सरणी, उनकी प्रकृति से, मूल्यों की एक श्रृंखला है)।

+0

Arrays मूल्यों की एक श्रृंखला नहीं हैं। Arrays * चर * की एक श्रृंखला है। वेरिएबल्स के संदर्भों के सरणी होने का कारण यह नहीं है कि ऐसा करना अजीब है; ऐसा करने के लिए यह पूरी तरह तार्किक है। ऐसा इसलिए है कि हमें स्टैक पॉइंटर को स्थानांतरित करके मूल्य प्रकार के स्थानीय चर के विलुप्त होने को अनुकूलित करने से रोकता है। * यही कारण है कि आप किसी फ़ील्ड या सरणी स्लॉट में चर के संदर्भ को संग्रहीत नहीं कर सकते हैं। –

+0

@Eric: जाहिर है आप सही हैं; मेरा कहना था कि सरणी वेरिएबल्स की एक श्रृंखला है जो संगत रूप से आवंटित की जाती है, इसलिए एक सरणी बनाने के लिए परिवर्तनीय संदर्भों की मनमानी सूची निर्दिष्ट करने में सक्षम होने से कोई अर्थ नहीं होगा। –

1

वास्तव में कोई रास्ता नहीं है। कैसे है किसी भी सिर्फ ऐसा करने से बेहतर है कि

public static void Main(string[] args) 
{ 
    BooleanWrapper a = true, b = true, c = true, d = true, e = new BooleanWrapper(); 
    b.SetTo(a, c, d, e); 
} 

public static void SetTo(this BooleanWrapper sourceWrapper, params BooleanWrapper[] wrappers) 
{ 
    foreach (var w in wrappers) 
     w.Value = sourceWrapper.Value; 
} 

public class BooleanWrapper 
{ 
    public BooleanWrapper() { } 

    public BooleanWrapper(Boolean value) 
    { 
     Value = value; 
    } 

    public Boolean Value { get; set; } 

    public static implicit operator BooleanWrapper(Boolean value) 
    { 
     return new BooleanWrapper(value); 
    } 
} 

लेकिन तब फिर से:

public static void Main(string[] args) 
{ 
    Boolean[] bools = new Boolean[5]; 
    bools.SetTo(bools[1]); // Note I changed the order of arguments. I think this makes more sense. 
} 

public static void SetTo(this Boolean[] bools, Boolean value) 
{ 
    for(int i = 0; i < bools.Length; i++) 
     bools[i] = value; 
} 

सब के बाद, एक सरणी चर का एक क्रम है आप कुछ इस तरह कर सकता है। यदि आपको चर की अनुक्रम की तरह व्यवहार करने की आवश्यकता है, तो एक सरणी का उपयोग करें।

+0

वह ऐसा कर सकता है लेकिन शून्य-संस्करणों के साथ - 'बूल?' या 'न्यूबल योग्य '। –

+0

नहीं, गुजरने के दौरान 'न्यूलबल की प्रतिलिपि बनाई जाती है (संदर्भ पारित करने के चरण में) और आप उनके मूल्य को भी म्यूट नहीं कर सकते हैं। – Joren

3

दुर्भाग्य से जावा का समुदाय, और अब .NET, डेवलपर्स ने फैसला किया कि "सुरक्षा" के नाम पर कम लचीलापन पसंदीदा समाधान है, और उसी परिणाम को प्राप्त करने के लिए आपको असाधारण जटिलता का चयन करना होगा (उन सभी वर्ग संरचनाओं, प्रतिनिधियों, आदि)।

डेल्फी में मैं बस कुछ इस तरह कर सकता है:

var 
    a: integer; f: double; n: integer; 
sscanf(fmtstr, valuestr, [@a, @f, @n]); 

// < - "sscanf" एक समारोह मैं अपने आप को लिखा है कि संकेत का एक खुला सरणी लेता है।

सी # में आप क्या करना है जाएगा:

int a; double f; int n; 
object [] o = new object[]; 
sscanf(fmtstr, valuestr, ref o); 
a = o[0]; 
f = o[1]; 
n = o[2]; 

क्या मैं डेल्फी कोड की 1 लाइन में कर सकता है ऐसा करने के लिए कोड के 5 लाइनों है कि। मुझे लगता है कि वहां कोई फॉर्मूला है कि कोड में बग की संभावना कोड की रेखाओं की संख्या के साथ ज्यामितीय रूप से बढ़ जाती है; इसलिए यदि आपके पास कोड की 20 लाइनें हैं तो आपके पास कोड होने की तुलना में 4 गुना अधिक बग होने की संभावना है।

बेशक, आप उन सभी अजीब कोण के साथ प्रतिनिधि का उपयोग कर कोड की अपनी # पंक्तियां घटा सकते हैं ब्रैकेट और अजीब वाक्यविन्यास, लेकिन मुझे लगता है कि यह भी बग के लिए एक स्वर्ग है।

सादगी के साथ क्या हुआ?

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