2012-06-13 100 views
13

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

public class Person 
{ 
    public ComplexId Id { get; set; } 
    public string Name { get; set; } 
    // ... 
} 

मैं इस तरह के दृष्टिकोण का उपयोग करता था, यह "सर्वोत्तम अभ्यास" जैसा है, है ना? स्थानांतरित डेटा स्टोर करने का यह सबसे अच्छा तरीका है? क्या होगा यदि मैं struct इस तरह के लिए इसे बदल:

public struct Peson 
{ 
    public ComplexIdentifier ComplexId; 
    public string Name; 
} 
public struct ComplexIdentifier 
{ 
    public int LocalId; 
    public int GlobalId; 
} 

इस बेहतर होगा प्रदर्शन/स्मृति उपयोग के नजरिए से रास्ता नहीं है? या शायद इस तरह से काम कर रहे कुछ प्रकार के जाल हैं?

+2

"कक्षा" (यह एक आसान था; पी) –

+0

सभी भाग लेने के लिए धन्यवाद! –

उत्तर

14

मानक डीटीओ इकाइयों के लिए, आप कक्षा के साथ रहना चाहेंगे।

struct कक्षाओं की तुलना में संभावित उपयोग मामलों की सीमा सीमित सीमित है। MSDN guidelines about value types में उल्लिखित अनुसार, struct प्रकार बहुत अधिक हो जाते हैं (भूलें, वे मूल्य प्रकार हैं और प्रतिलिपि कॉपी किए गए हैं)। नहीं gotchas के बहुत उल्लेख करने के लिए जब आप इसे बॉक्स जब इंटरफेस संदर्भित struct प्रकार गुण के माध्यम से अवगत कराया होने शुरू करते हैं, या गलती से, या उन्हें परिवर्तनशील बनाने ...

मैं मैं saying not to usestruct जब यह प्रासंगिक है, लेकिन नहीं कर रहा हूँ बहुत शायद ही कभी मुझे अपने मुख्य डेस्कटॉप एप्लिकेशन में struct प्रकारों का उपयोग करने की आवश्यकता है - जो स्तरित है और डीटीओ प्रकारों को दिखाता है।


प्रदर्शन समस्या का उत्तर struct बनाम class के रूप में उत्तर नहीं दिया जा सकता है। हॉटस्पॉट खोजने और वहां से जाने के लिए आपको dotTrace या ANTS जैसे एक प्रोफाइलिंग टूल को नियोजित करने की आवश्यकता होगी। प्रदर्शन के मुद्दे छोटे नहीं हैं और अच्छी टूलिंग आमतौर पर उत्तर की शुरुआत होती है।

+1

+1। एक विज्ञापन: [उत्परिवर्तनीय structs EVIL !!] (http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil) – Steven

+0

@Steven बेशक, मैंने अपने उत्तर में यह लिंक जोड़ा है - subliminally तरह ;-) –

+0

सहमत हैं। इन वस्तुओं से और उससे मूल्यों की प्रतिलिपि बनाने के आसपास कुछ सिरदर्द को कम करने के लिए, लाभ [ऑटोमैपर] (automapper.org)। – bluevector

4

क्या यह प्रदर्शन/स्मृति उपयोग परिप्रेक्ष्य से बेहतर तरीका होगा?

सं। संरचनाएं मूल्य प्रकार हैं, इसलिए वे मूल्य द्वारा प्रतिलिपि बनाई गई हैं। इसका मतलब है कि केवल एक संदर्भ की प्रतिलिपि बनाने के बजाय, आप हमेशा पूर्ण वस्तु की प्रतिलिपि बनायेंगे। यदि कुछ भी हो, तो यह शायद थोड़ा धीमा हो जाएगा और अधिक मेमोरी का उपयोग करेगा (क्योंकि ऑब्जेक्ट डुप्लिकेट होगा)।

एक और कारण यह है कि आपको ऐसा क्यों नहीं करना चाहिए: उत्परिवर्तनीय structs हमेशा से बचा जाना चाहिए, क्योंकि यदि आप सावधान नहीं हैं तो वे अप्रत्याशित व्यवहार कर सकते हैं।

2

struct अधिक खतरनाक हो सकता है कि CLR द्वारा मूल्य प्रकारों को और अधिक अलग तरीके से संभाला जाता है और यदि खराब लिखा जाता है (उदा। एक परिवर्तनीय संरचना) भयानक सिरदर्द पैदा कर सकता है। इसके अलावा, यदि आपके प्रकार में कई फ़ील्ड हैं और फिर विधि से विधि में पारित किया गया है, तो आप प्रत्येक विधि कॉल पर प्रत्येक फ़ील्ड के मान की प्रतिलिपि बनायेंगे, इस प्रकार यदि आप पहले स्थान पर कक्षा का उपयोग करते हैं तो अधिक मेमोरी का उपयोग कर रहे हैं।

DTO (डेटा स्थानांतरण ऑब्जेक्ट्स) का उपयोग जो राज्य और व्यवहार को अलग करने के लिए प्रोत्साहित करेगा। यदि सही तरीके से किया जाता है तो यह एक अच्छा डिजाइन हो सकता है (और ज्यादातर मामलों में आप कक्षाओं का उपयोग करके इस पैटर्न को लागू करेंगे, न कि structs)।

इसके अलावा, struct का उपयोग करने के विशिष्ट मामले DTO object के रूप में त्रुटिपूर्ण लगता है, क्योंकि यह अनावश्यक redundancy प्रस्तुत करता है। चूंकि structs cannot inherit other structs, आप व्यक्त नहीं कर सकते हैं-एक रिश्ते। Customer पर Person से प्राप्त होने पर आप क्या करते हैं। क्या आप Person properties in the Customer संरचना को दोहराते हैं? क्या आप एक ग्राहक संरचना के अंदर एक व्यक्ति संरचना घोंसला करते हैं? न तो दृष्टिकोण आदर्श है। यदि आप कम से कम कक्षाओं का उपयोग करते हैं, आप ग्राहक को व्यक्ति बढ़ा सकते हैं।

1

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

0

मेरी राय है: कक्षाएं बेहतर हैं।

कक्षाओं के साथ आप INotifyPropertyChanged इंटरफ़ेस को कार्यान्वित कर सकते हैं यदि आप डेटाबेसिंग करते हैं तो बहुत उपयोगी होगा।

आप "आईडी" जैसे कुछ निजी फ़ील्ड्स भी प्राप्त कर सकते हैं, केवल "get" -property, आप अपनी कक्षा में कुछ विधियां जोड़ सकते हैं, आप अपनी संस्थाओं को क्रमबद्ध कर सकते हैं।
मैं बस इतना कहना चाहता हूं कि आप कक्षाओं के साथ अधिक लचीला हैं, और मुझे नहीं लगता कि उस मामले में संरचना और कक्षाओं के बीच कोई बड़ा प्रदर्शन अंतर है। http://msdn.microsoft.com/en-us/library/ee817644.aspx

वहाँ एक नज़र डालें:

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

+0

मैं स्टेटलेस कक्षाओं का उपयोग कर रहा हूं - मुझे इनोटिफ़ाईप्रॉपर्टी के बारे में पता है लेकिन मेरे कार्य के अनुसार मुझे इसकी आवश्यकता नहीं है। मुझे इस ऑब्जेक्ट्स में किसी भी तर्क (विधियों) को जोड़ने की आवश्यकता नहीं है। और केवल गुण प्राप्त करें - संरचना में केवल पढ़ने वाले फ़ील्ड हो सकते हैं, क्या यह हो सकता है? –

+0

हाँ, आप सही हैं। खराब उदाहरण के लिए खेद है। – sickUnit

5

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

धारणा है कि परिवर्तनशील structs बुराई दिनांकों वापस कुछ जल्दी सी # संकलक करने के लिए जो कर रहे हैं, जिसमें

 
    SomeReadonlyStruct.SomeProperty = 5; 

चुपचाप में संकलक से बदल दिया जाएगा: केवल पढ़ने के गुण के पीछे

 
    var temp = SomeReadonlyStruct; 
    temp.SomeProperty = 5; 

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

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

पर विचार करें निम्नलिखित कोड:

 
    customerPhone = someDataSource.GetPhoneNumber(customerID); 
    customerPhone.Extention = "5309" 

कुछ लोगों को तथ्य यह है कि अगर customerPhone एक उजागर मैदान struct है, Extension संपत्ति की स्थापना someDataSource में जानकारी को प्रभावित नहीं करेगा नापसंद करते हैं। हालांकि यह निश्चित रूप से सच है कि एक संरचना क्षेत्र लिखना किसी और चीज को अपडेट नहीं करेगा, यह customerPhone एक परिवर्तनीय वर्ग प्रकार था, तो यह अस्तित्व की तुलना में एक बेहतर स्थिति है। कोई भी जो customerPhone समझता है, एक खुला क्षेत्रीय संरचना प्रकार पता चलेगा कि उसके सदस्यों में परिवर्तन किसी और चीज को प्रभावित नहीं करेंगे। इसके विपरीत, यदि customerPhone एक म्यूटेबल क्लास प्रकार है, तो ऊपर दिए गए कोड को customerID से जुड़े फ़ोन नंबर को बदलकर अपडेट कर सकते हैं। या यह नहीं हो सकता है। या, यदि एक फोन नंबर दो customerID मानों से जुड़ा हुआ था, तो उपर्युक्त कोड दोनों को बदल सकता है। कोड कोड की मात्रा को यह निर्धारित करने के लिए अध्ययन करना पड़ सकता है कि उपर्युक्त कोड के प्रभाव और दुष्प्रभाव कितने बड़े हो सकते हैं। इससे भी बदतर, यह सुनिश्चित करना मुश्किल हो सकता है कि किसी ने कुछ भी याद नहीं किया है।

निश्चित रूप से कुछ जगहें हैं जहां कक्षा ऑब्जेक्ट संदर्भों के चारों ओर गुज़रने से structs के चारों ओर गुजरने से अधिक कुशल हो सकता है। ऐसे कुछ मामले भी हैं जहां म्यूटेबल क्लास ऑब्जेक्ट्स कक्षा के भीतर उपयोगी डेटा धारक हो सकते हैं। कुछ जेनेरिक रैपर, हालांकि, एक परिवर्तनीय या अपरिवर्तनीय वर्ग, में एक संरचना को लपेटने और उन प्रकार के वर्गों के बीच की जानकारी का आदान-प्रदान करने में सक्षम हो सकते हैं।

 
interface IReadableHolder<T> { T Value {get;} } 

class MutableHolder<T> : IReadableHolder<T> 
{ 
    public T Value; 
    IReadableHolder.Value {get {return Value;} } 
    public MutableHolder(T newValue) { Value = newValue; } 
    public MutableHolder(IReadableHolder<T> it) { Value = it.Value; } 
} 
class ImmutableHolder<T> : IReadableHolder<T> 
{ 
    T _Value; 
    public Value {get {return _Value;} } 
    public ImmutableHolder(T newValue) { _Value = newValue; } 
} 

ऐसा निर्माण म्यूटेबल structs के बिना और अधिक अजीब होगा।

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

  • कोई संबंधित समस्या नहीं^_^