C # - एक सूची में कई सामान्य प्रकार


153

यह संभव नहीं है, लेकिन मेरे पास यह वर्ग है:

public class Metadata<DataType> where DataType : struct
{
    private DataType mDataType;
}

इसके लिए और भी बहुत कुछ है, लेकिन चलो इसे सरल रखें। जेनेरिक प्रकार (DataType) जहां कथन द्वारा मान प्रकारों तक सीमित है। जो मैं करना चाहता हूं, वह इन मेटाडेटा ऑब्जेक्ट्स की अलग-अलग प्रकारों (डेटा टाइप) की एक सूची है। जैसे कि:

List<Metadata> metadataObjects;
metadataObjects.Add(new Metadata<int>());
metadataObjects.Add(new Metadata<bool>());
metadataObjects.Add(new Metadata<double>());

क्या यह भी संभव है?


24
मुझे आश्चर्य है कि क्या सिर्फ एक का उपयोग करने की तुलना में नीचे दिए गए उत्तरों में दृष्टिकोण का कोई वास्तविक लाभ है List<object>? वे मुक्केबाजी / अनबॉक्सिंग को नहीं रोकेंगे, वे कास्टिंग की आवश्यकता को दूर नहीं करेंगे, और अंततः, आपको एक ऐसी Metadataवस्तु मिल रही है जो आपको वास्तविक के बारे में कुछ भी नहीं बताती है DataType, मैं उन मुद्दों को हल करने के लिए एक समाधान खोज रहा था। यदि आप एक इंटरफ़ेस / वर्ग की घोषणा करने जा रहे हैं, तो बस एक सामान्य सूची में लागू / व्युत्पन्न सामान्य प्रकार को लागू करने में सक्षम होने के लिए, बस एक निरर्थक परत होने के अलावा अन्य का उपयोग करने की तुलना में कितना अलग है List<object>?
साब अमीनी

9
एब्सट्रैक्ट बेस क्लास और इंटरफ़ेस दोनों ही प्रकार के तत्वों को प्रतिबंधित करके नियंत्रण की एक डिग्री प्रदान करते हैं जिन्हें सूची में जोड़ा जा सकता है। मैं यह भी नहीं देख सकता कि इसमें मुक्केबाजी कैसे आती है।
0b101010

3
बेशक, यदि आप .NET v4.0 या उच्चतर का उपयोग कर रहे हैं, तो सहसंयोजक समाधान है। List<Metadata<object>>उसने चाल चली।
0b101010

2
@ 0b101010 मैं भी यही सोच रहा था, लेकिन दुर्भाग्य से मूल्य प्रकारों पर विचरण की अनुमति नहीं है। चूंकि ओपी के पास एक structबाधा है, इसलिए यह यहां काम नहीं करता है। देखें
नवाफल

@ 0b101010, दोनों ही संदर्भ प्रकारों को प्रतिबंधित करते हैं, किसी भी निर्मित मूल्य प्रकार और किसी भी संरचना को अभी भी जोड़ा जा सकता है। इसके अलावा, अंत में, आपके पास MetaDataप्रत्येक मूल तत्व प्रकार के बारे में जानकारी (संकलित समय) के साथ अपने मूल मूल्य प्रकारों के बजाय संदर्भ प्रकारों की एक सूची है , जो प्रभावी रूप से "बॉक्सिंग" है।
साहिब अमीनि

जवाबों:


195
public abstract class Metadata
{
}

// extend abstract Metadata class
public class Metadata<DataType> : Metadata where DataType : struct
{
    private DataType mDataType;
}

5
वाह! मैं सच में नहीं लगता था कि यह संभव था! तुम एक जीवन रक्षक हो, यार!
कार्ल

2
इसके लिए +10! मैं नहीं जानता कि यह क्यों संकलन करता है .. वास्तव में मुझे क्या चाहिए!
ओडीस

मुझे एक समान समस्या है, लेकिन मेरा सामान्य वर्ग दूसरे सामान्य वर्ग से मिलता है, इसलिए मैं आपके समाधान का उपयोग नहीं कर सकता ... इस स्थिति के लिए कोई विचार?
शेरिडन

10
क्या एक सरल की तुलना में इस दृष्टिकोण का कोई लाभ है List<object>? कृपया ओपी के प्रश्न के तहत पोस्ट की गई मेरी टिप्पणी को देखें।
साब अमीनी

11
@SaebAmini एक सूची <ऑब्जेक्ट> एक डेवलपर के लिए कोई इरादा नहीं दिखाता है, और न ही यह किसी डेवलपर को गलती से सूची में कुछ गैर-मेटाडेटा ऑब्जेक्ट जोड़कर पैर में शूटिंग करने से रोकता है। सूची <मेटाडेटा> का उपयोग करके यह समझा जाता है कि सूची में क्या होना चाहिए। सबसे अधिक संभावना मेटाडाटा में कुछ सार्वजनिक गुण / तरीके होंगे जो उपरोक्त उदाहरणों में नहीं दिखाए गए हैं। ऑब्जेक्ट के माध्यम से उन तक पहुंचने पर बोझिल कलाकारों की आवश्यकता होगी।
बज़

92

लेप्पी के जवाब के बाद, MetaDataएक इंटरफ़ेस क्यों न बनाएं :

public interface IMetaData { }

public class Metadata<DataType> : IMetaData where DataType : struct
{
    private DataType mDataType;
}

क्या कोई मुझे बता सकता है कि यह दृष्टिकोण बेहतर क्यों है?
लाजो

34
क्योंकि कोई भी सामान्य कार्यक्षमता साझा नहीं की जाती है - फिर उस पर एक आधार वर्ग को क्यों बर्बाद करें? एक इंटरफ़ेस पर्याप्त है
21

2
क्योंकि आप संरचना में इंटरफेस को लागू कर सकते हैं।
डेमियन लेस्ज़्स्की - वश

2
आभासी तरीकों का उपयोग करते हुए वर्ग की विरासत, हालांकि, इंटरफ़ेस विधियों की तुलना में लगभग 1.4 गुना तेज है। इसलिए यदि आप मेटाडेटा <DataType> में किसी भी गैर-जेनेरिक मेटाडेटा (वर्चुअल) विधियों / गुणों को लागू करने की योजना बनाते हैं, तो प्रदर्शन एक चिंता का विषय है, इंटरफ़ेस के बजाय एक सार वर्ग चुनें। अन्यथा, इंटरफ़ेस का उपयोग करना अधिक लचीला हो सकता है।
TamusJRoyce

30

मैंने newकीवर्ड का उपयोग करते हुए एक गैर-जेनेरिक संस्करण का भी उपयोग किया है :

public interface IMetadata
{
    Type DataType { get; }

    object Data { get; }
}

public interface IMetadata<TData> : IMetadata
{
    new TData Data { get; }
}

स्पष्ट इंटरफ़ेस कार्यान्वयन का उपयोग दोनों Dataसदस्यों को अनुमति देने के लिए किया जाता है :

public class Metadata<TData> : IMetadata<TData>
{
    public Metadata(TData data)
    {
       Data = data;
    }

    public Type DataType
    {
        get { return typeof(TData); }
    }

    object IMetadata.Data
    {
        get { return Data; }
    }

    public TData Data { get; private set; }
}

आप मूल्य प्रकारों को लक्षित करने वाले संस्करण प्राप्त कर सकते हैं:

public interface IValueTypeMetadata : IMetadata
{

}

public interface IValueTypeMetadata<TData> : IMetadata<TData>, IValueTypeMetadata where TData : struct
{

}

public class ValueTypeMetadata<TData> : Metadata<TData>, IValueTypeMetadata<TData> where TData : struct
{
    public ValueTypeMetadata(TData data) : base(data)
    {}
}

इसे किसी भी प्रकार की सामान्य बाधाओं तक बढ़ाया जा सकता है।


4
+1 सिर्फ इसलिए कि आप इसे उपयोग करने का तरीका दिखा रहे हैं ( DataTypeऔर object Dataबहुत मदद की है)
Odys

4
मैं उदाहरण के लिए लिखने में सक्षम नहीं लगता Deserialize<metadata.DataType>(metadata.Data);। यह बताता है कि मैं प्रतीक मेटाडेटा को हल नहीं कर सकता । एक सामान्य विधि के लिए इसका उपयोग करने के लिए DataType को कैसे पुनः प्राप्त करें?
कूर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.