2009-04-23 9 views
12

मेरे पास एक कक्षा है जिसे मुझे एक या दो तरीकों से एक-दूसरे के बाद कई बार कॉल करना पड़ता है। वर्तमान में विधियां void लौटती हैं। मैं सोच रहा था, क्या यह बेहतर होगा कि यह this लौटाए, ताकि विधियों को घोंसला जा सके? या यह बहुत बहुत बुरा माना जाता है? या यदि बुरा है, तो यह बेहतर होगा अगर यह उसी प्रकार की एक नई वस्तु वापस कर देता है? या आप क्या सोचते हैं?सी #: विधि घोंसले के लिए 'यह' लौट रहा है?

var a = new Adder(); 
    a.Add(4); 
    a.Remove(1); 
    a.Add(7); 
    a.Remove(3); 

अन्य दो इस तरह से इस्तेमाल किया जा सकता:

var a = new Adder() 
     .Add(4) 
     .Remove(1) 
     .Add(7) 
     .Remove(3); 

// Regular 
class Adder 
{ 
    public Adder() { Number = 0; } 

    public int Number { get; private set; } 

    public void Add(int i) { Number += i; } 
    public void Remove(int i) { Number -= i; } 
} 

// Returning this 
class Adder 
{ 
    public Adder() { Number = 0; } 

    public int Number { get; private set; } 

    public Adder Add(int i) { Number += i; return this; } 
    public Adder Remove(int i) { Number -= i; return this; } 
} 

// Returning new 
class Adder 
{ 
    public Adder() : this(0) { } 
    private Adder(int i) { Number = i; } 

    public int Number { get; private set; } 

    public Adder Add(int i) { return new Adder(Number + i); } 
    public Adder Remove(int i) { return new Adder(Number - i); } 
} 

पहले एक इस तरह से इस्तेमाल किया जा सकता: एक उदाहरण के रूप में मैं एक योजक वर्ग के तीन संस्करण बनाया है

जहां केवल अंतर यह है कि a पहले मामले में new Adder() है जबकि बाद में यह अंतिम विधि का परिणाम है।

सबसे पहले मुझे लगता है कि जल्दी से ... बार-बार लिखने के लिए परेशान हो रहा है। तो मैं अन्य संस्करणों में से एक का उपयोग करना चाहता हूं।

तीसरा काम कई अन्य तरीकों की तरह है, जैसे कई स्ट्रिंग विधियों और आईनेमरेबल एक्सटेंशन विधियां। मुझे लगता है कि इसमें सकारात्मक पॉजिटिव है कि आप var a = new Adder(); var b = a.Add(5); जैसी चीजें कर सकते हैं और उसके बाद 0 था और वह 5 था। लेकिन साथ ही, क्या यह हर समय नई वस्तुओं को बनाने के लिए थोड़ा महंगा नहीं है? और पहली वस्तु कब मर जाएगी? जब पहली विधि किस तरह से लौटती है? या?

वैसे भी, मुझे वह पसंद है जो this देता है और मुझे लगता है कि मैं इसका उपयोग करूंगा, लेकिन मुझे यह जानकर बहुत उत्सुकता है कि दूसरे इस मामले के बारे में क्या सोचते हैं। और सबसे अच्छा अभ्यास क्या माना जाता है।

+1

आप तीसरे वर्ग में ऐसा नहीं करते जो आपने कहा था। आप संख्या से जोड़ या घटाएंगे और इसे नए एडर (...) में एक अलग पूर्णांक के रूप में पास करेंगे। – Samuel

+0

ओह, अच्छा पकड़ो! धन्यवाद =) – Svish

उत्तर

17

'इसे वापस करें' शैली को कभी-कभी fluent interface कहा जाता है और यह एक आम प्रथा है।

+0

आह। ठंडा। तो मुझे लगता है कि मैं उसके लिए जाऊंगा =) – Svish

+2

ध्यान दें कि धाराप्रवाह शैली एक बहुत ही अलग विकल्प के समान लिखती है, जो आपके ऑब्जेक्ट को अपरिवर्तनीय बनाने और आंतरिक स्थिति को संशोधित करने के बजाय आपके ऑब्जेक्ट के नए उदाहरण लौटाती है। उदाहरण में एक की तरह एक साधारण वर्ग के साथ (यह नहीं कि उदाहरण बहुत यथार्थवादी है) तो आप इसके बजाय इसे अपरिवर्तनीय बनाने के पेशेवरों और विपक्षों पर विचार करना चाहेंगे। – mquander

+2

दोनों 'इसे वापस लौटें' और 'नया लौटें' विभिन्न अनुप्रयोगों के साथ उदाहरण हैं: jQuery '$ ('# eleId')। दिखाएं() 'यह' देता है क्योंकि अन्यथा यह eleId की एक प्रति बना देगा। लिंक 'myCollection.Where (x => x.IsValid)' एक नई वस्तु देता है क्योंकि अन्यथा यह मेरे चयन को बदल देता, जो अपरिवर्तनीय हो सकता है। – Keith

0

इस पर विचार करें: यदि आप 5 साल में इस कोड पर वापस आते हैं, तो क्या यह आपको समझने जा रहा है? यदि ऐसा है, तो मुझे लगता है कि आप आगे बढ़ सकते हैं।

इस विशिष्ट उदाहरण के लिए, हालांकि, ऐसा लगता है कि + और - ऑपरेटरों को अधिभारित करना चीजों को स्पष्ट और एक ही चीज़ को पूरा करेगा।

+0

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

+0

जब आप 5 साल में वापस आते हैं तो छोड़कर। एक विधि श्रृंखला तुरंत एक माउस होवर के साथ प्रकट होने जा रही है जबकि ऑपरेटरों को कक्षा को स्वयं की आवश्यकता होती है। – Samuel

+0

आह, यह एक अच्छा बिंदु हां है। – Svish

6

मुझे "धाराप्रवाह वाक्यविन्यास" पसंद है और दूसरा ले जाएगा। आखिरकार, आप अभी भी इसे पहले के रूप में उपयोग कर सकते हैं, जो लोग धाराप्रवाह वाक्यविन्यास के साथ असहज महसूस करते हैं।

एक और विचार एडर की तरह एक अंतरफलक एक आसान उपयोग करने के लिए बनाने के लिए:

public Adder Add(params int[] i) { /* ... */ } 
public Adder Remove(params int[] i) { /* ... */ } 

Adder adder = new Adder() 
    .Add(1, 2, 3) 
    .Remove(3, 4); 

मैं हमेशा छोटा और आसान पढ़ने-में-इंटरफेस बनाने की कोशिश, लेकिन कई लोगों के रूप में के रूप में जटिल कोड लिखना पसंद मुमकिन।

+0

पैराम उपयोग के साथ कूल विचार। शायद खुद का उपयोग करें .... – Svish

0
  1. आपके विशिष्ट मामले के लिए, अंकगणितीय ऑपरेटरों को अधिभारित करना शायद सबसे अच्छा समाधान होगा।

  2. रिटर्निंग this (फ्लुएंट इंटरफ़ेस) अभिव्यक्तियां बनाने के लिए सामान्य अभ्यास है - यूनिट परीक्षण और मॉकिंग फ्रेमवर्क इसका बहुत उपयोग करते हैं। Fluent Hibernate एक और उदाहरण है।

  3. एक नया उदाहरण लौटाना भी एक अच्छा विकल्प हो सकता है। यह आपको अपनी कक्षा को अपरिवर्तनीय बनाने की अनुमति देता है - आम तौर पर मल्टीथ्रेडिंग के मामले में एक अच्छी चीज और बहुत आसान। लेकिन अपरिवर्तनीयता आपके लिए कोई उपयोग नहीं होने पर ऑब्जेक्ट निर्माण ओवरहेड के बारे में सोचें।

+0

अच्छी तरह से सारांशित = = – Svish

0

यदि आप इसे एडर कहते हैं, तो मैं इसे वापस करने के साथ जाऊंगा। हालांकि, एक एडर वर्ग के लिए उत्तर देने के लिए यह अजीब तरह का अजीब है।

आप इसे MyNumber की तरह कुछ बनाने और एक जोड़ें() - विधि बनाने पर विचार कर सकते हैं।

आदर्श रूप में (IMHO), कि है कि आपके उदाहरण के अंदर संग्रहित नंबर बदल नहीं होगा, लेकिन नए मान के साथ एक नया उदाहरण बनाने के लिए, जो आप वापस:

class MyNumber 
{ 
    ... 

    MyNumber Add(int i) 
    { 
     return new MyNumber(this.Value + i); 
    } 
} 
+0

ठीक है, ज़ाहिर है। और यहां तक ​​कि अजनबी को निकालने के लिए एक विधि भी शामिल है, जिसे वास्तव में घटाया जाना चाहिए था। लेकिन यह यहां बिंदु नहीं था: पी – Svish

0

मुझे लगता है कि सरल इंटरफेस के लिए है कि, "धाराप्रवाह" इंटरफ़ेस बहुत उपयोगी है, खासकर क्योंकि यह लागू करना बहुत आसान है। धाराप्रवाह इंटरफ़ेस का मूल्य यह है कि यह समझने के तरीके में प्राप्त होने वाले बहुत से अपर्याप्त फ़्लफ को समाप्त करता है। ऐसे इंटरफ़ेस को विकसित करने में काफी समय लग सकता है, खासकर जब इंटरफ़ेस शामिल होना शुरू होता है। आपको इस बारे में चिंता करनी चाहिए कि इंटरफ़ेस का उपयोग "पढ़ता है"; मेरे दिमाग में, इस तरह के एक इंटरफ़ेस के लिए सबसे अधिक आकर्षक उपयोग यह है कि यह प्रोग्रामर के इरादे को कैसे संचारित करता है, न कि वर्णों की संख्या को बचाता है।

अपने विशिष्ट प्रश्न का उत्तर देने के लिए, मुझे "इसे वापस" शैली पसंद है। धाराप्रवाह इंटरफेस का मेरा सामान्य उपयोग विकल्पों के एक सेट को परिभाषित करना है। यही है, मैं कक्षा का एक उदाहरण बना देता हूं और फिर ऑब्जेक्ट के वांछित व्यवहार को परिभाषित करने के लिए उदाहरण पर धाराप्रवाह विधियों का उपयोग करता हूं। अगर मेरे पास हाँ/नहीं विकल्प है (लॉगिंग के लिए कहें), तो मुझे "सेट लॉजिंग (बूल स्टेट)" विधि नहीं है बल्कि दो विधियों "साथ लॉजिंग" और "बिना लॉजिंग" करने की कोशिश करें। यह कुछ और काम है लेकिन अंतिम परिणाम की स्पष्टता बहुत उपयोगी है।

2

श्रृंखलन के लिए एक अच्छी बात है और कुछ चौखटे में मूल है (उदाहरण के Linq एक्सटेंशन के लिए और jQuery दोनों भारी उपयोग करें)।

आप एक नई वस्तु बनाने चाहे या return this आप कैसे अपने प्रारंभिक वस्तु व्यवहार करने की उम्मीद पर निर्भर करता है:

var a = new Adder(); 

var b = a.Add(4) 
     .Remove(1) 
     .Add(7) 
     .Remove(3); 

//now - should a==b ? 

jQuery में श्रृंखलन अपने मूल वस्तु को बदल दिया है - यह इस वापस आ गया है। यह अपेक्षित व्यवहार है - अन्यथा मूल रूप से UI तत्वों को क्लोन करें।

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

कौन सा पैटर्न बेहतर है कि आप क्या कर रहे हैं?

+0

लिंक और jQuery के पीछे सोच के बारे में अच्छा अवलोकन =) इस सटीक मूर्ख मामले में, "एक == बी" होना चाहिए, उन्हें निश्चित रूप से बराबर माना जाना चाहिए क्योंकि उनके पास वही संख्या लेकिन अगर आपने विधि 2 या 3 का उपयोग किया है, तो संदर्भों को वास्तव में वही होना जरूरी नहीं होगा। – Svish

+0

यदि आप ऑपरेशन पूरा करने के बाद हर बार 'नया' का उपयोग करते हैं। Number == 1 जबकि b.Number == 7. यदि आप इसके बजाय 'n' का उपयोग करते हैं तो number == 7 भी। – Keith

0

दूसरे और तीसरे समाधान के बीच मुख्य अंतर यह है कि इस के बजाय एक नया उदाहरण वापस लौट कर आप "पकड़" एक निश्चित स्थिति में वस्तु और उस से जारी रखने के लिए सक्षम हैं।

var a = new adder() .एड (4);

var b = a.Remove (1);

var c = a.Add (7) ।(3) निकालें;

इस मामले में दोनों बी और सी राज्य को प्रारंभिक बिंदु के रूप में कब्जा कर लिया है। Growing Object-Oriented Software, Guided by Tests by Steve Freeman; Nat Pryce में टेस्ट डोमेन ऑब्जेक्ट्स बनाने के लिए पैटर्न के बारे में पढ़ने के दौरान मैं इस मुहावरे में आया था।

अपने उदाहरणों के जीवनकाल के बारे में आपके प्रश्न पर: मैं उन्हें निकालने या जोड़ के आवेदक के रूप में जल्द ही कचरा संग्रह के लिए समझदार होने की उम्मीद करता हूं।

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