2013-12-15 3 views
5

इस प्रश्न का पालन करें: Why is Nullable<T> considered a struct and not a class?क्या इन लगभग समान वर्गों को एक में जोड़ने का कोई तरीका है?

मेरे पास दो कक्षाएं हैं जो अनिवार्य रूप से किसी आंतरिक ऑब्जेक्ट के साथ कुछ उपयोगकर्ता द्वारा प्रदत्त मान का टुपल बनाए रखती हैं।

जब उपयोगकर्ता द्वारा प्रदत्त मूल्य का प्रकार एक आदिम है, तो मुझे इसे Nullable<T> में लपेटना होगा ताकि यह टुपल में शून्य मान ले सके।

public class BundledClass<T> where T : class 
{ 
    private Tuple<T, object> _bundle; 
    public T Value 
    { 
     get { return _bundle == null ? null : _bundle.Item1; } 
     set { _bundle = new Tuple<T, object>(value, internalObj); } 
    } 
    //... 

public class BundledPrimitive<T> where T : struct 
{ 
    private Tuple<T?, object> _bundle; 
    public T? Value 
    { 
     get { return _bundle == null ? null : _bundle.Item1; } 
     set { _bundle = new Tuple<T?, object>(value, internalObj); } 
    } 
    //... 

मैं इसे पसंद करते हैं, तो मैं एक ही वर्ग है कि एक प्रकार पैरामीटर के रूप में या तो पुरातन या वर्गों ले जा सकते हैं के साथ ऐसा कर सकता है, लेकिन मैं इसे चारों ओर किसी भी तरह से नहीं दिख रहा। कुछ प्रकार के कस्टम Nullable कक्षा के साथ आने के बिना नहीं, जो कि किसी भी प्रकार के बॉक्स (केवल where T:struct प्रकार नहीं) को बॉक्स कर सकता है ताकि यह सुनिश्चित किया जा सके कि Value हमेशा शून्य हो सकता है;

ऐसा लगता है कि मैं कम से कम के रूप में

public class BundledPrimitive<T> : BundledClass<T?> { } 

उत्तरार्द्ध वर्ग को परिभाषित करने के लिए सक्षम होना चाहिए लेकिन फिर भी है कि Nullable<T> के बाद से विफल रहता है : class बाधा को पूरा नहीं करता (लिंक किए गए सवाल के अनुसार)।

+0

अगर मैं इस वर्ग की एक उपयोगकर्ता हूं, मैं कैसे के बीच अंतर है 'मान' स्थापित किया जा रहा नहीं और मुझे सेट होने मेरे कार्यक्रम में कहीं और शून्य 'मूल्य'? –

+0

@mikez अगर मान कभी सेट नहीं किया गया है, तो आंतरिक '_bundle = null'। यदि 'वैल्यू 'को शून्य पर सेट किया गया था, तो आंतरिक' _ बंडल' 'टुपल (शून्य, आंतरिक ओबीजे) होगा। यह महत्वपूर्ण नहीं है, लेकिन उपयोगकर्ता इसे सार्वजनिक-केवल संपत्ति का उपयोग करके देख सकता है जो '_bundle' लौटाता है। – Alain

+0

हां यह आंतरिक स्थिति में अंतर होगा, लेकिन एक कॉलर के रूप में मुझे '_bundle' तक पहुंच नहीं है। –

उत्तर

5

तो आप बस इस तरह अपने वर्ग के लिए बनाया गया:

Bundled<string> foo; // handles classes 
Bundled<float?> bar; // handles structs 

केवल समस्या: एक Nullable<T> के रूप में प्रकार पैरामीटर निर्दिष्ट करने, उदाहरण के लिए द्वारा

public abstract class Bundled<T> 
{ 
    private Tuple<T, object> _bundle; 
    public T Value 
    { 
     get { return _bundle == null ? default(T) : _bundle.Item1; } 
     set { _bundle = new Tuple<T, object>(value, internalObj); } 
    } 
} 

तो फिर तुम यह एक struct के साथ उपयोग कर सकते हैं यहां यह है कि यह संभव है कि कोई उपयोगकर्ता इस कक्षा का उपयोग गैर-शून्य संरचना — उदाहरण के साथ कर सके Bundled<int>। अगर वह वास्तव में अपने आवेदन में एक चिंता का विषय है, तो आप इस तरह अधिक विशिष्ट उप-प्रकार की घोषणा कर सकता है:

public class BundledClass<T> : Bundled<T> where T : class { } 
public class BundledStruct<T> : Bundled<T?> where T : struct { } 

तुम भी Bundled<T> आंतरिक के लिए निर्माता बना सकते हैं, तो यह आपके विधानसभा के बाहर से नहीं कहा जा सकता। इससे यह सुनिश्चित होगा कि उपयोगकर्ता आपके BundledClass/BundledStruct रैपर को बाईपास करने के लिए कस्टम उप-प्रकार नहीं बनायेगा।

+1

'डिफ़ॉल्ट (टी)' का उपयोग नहीं कर सकता। यदि उपयोगकर्ता 'बंडल foo' बनाता है, तो मुझे बिल्कुल' foo.Value = 0' बनाम 'foo' सेट करने के बीच अंतर करना होगा।मान' अनसेट है (और इस प्रकार '_bundle = tuple (शून्य, आंतरिक ओबीजे)')। – Alain

+0

@Alain मेरा अद्यतन उत्तर देखें। –

+0

मुझे लगता है कि काम के साथ-साथ नीचे जवाब भी काम करेगा, जब तक कि कोई भी टाइप प्रकार की बाधा के बिना 'बंडल ' लागू करने का प्रयास करता है। – Alain

2

सबसे अच्छा मैं अभी के साथ आ सकता था। यह अभी भी दो वर्गों है, लेकिन यह मेरे कोड दोहराव की तर्ज के सैकड़ों से बचाता है:

public abstract class Bundled<T> 
{ 
    protected Tuple<T, object> _bundle; 
    public abstract T Value { get; set; } 

    //... Everything else 
} 

public class BundledClass<T> : Bundled<T> where T : class 
{ 
    public sealed override T Value 
    { 
     get { return _bundle == null ? null : _bundle.Item1; } 
     set { _bundle = new Tuple<T, object>(value, internalObj); } 
    } 
} 

public class BundledPrimitive<T> : Bundled<T?> where T : struct 
{   
    public sealed override T? Value 
    { 
     get { return _bundle == null ? null : _bundle.Item1; } 
     set { _bundle = new Tuple<T?, object>(value, internalObj); } 
    } 
} 
संबंधित मुद्दे