2012-10-10 19 views
5

मैं अपने संस्थाओं के लिए आधार वर्ग हैजेनरिक की सूची बनाएं

public class Entity<T> where T : Entity<T>, new() 
{ 
    public XElement ToXElement() 
    { 
    } 
    public static T FromXElement(XElement x) 
    { 
    } 
} 

क्योंकि मैं स्थिर विधि FromXElement भी दृढ़ता से टाइप किए जाने की चाहते मैं, यह अजीब निर्माण Entity<T> where T : Entity<T> उपयोग करने के लिए है, मैं, कुछ संस्थाओं है की तरह कि

public class Category : Entity<Category> 
{ 
} 
public class Collection : Entity<Collection> 
{ 
} 

मैं बेस क्लास का उपयोग करके अपनी संस्थाओं की सामान्य सूची कैसे बना सकता हूं?

var list = new List<Entity<?>>(); 
list.Add(new Category()); 
list.Add(new Collection()); 
+0

आप क्या करने की कोशिश कर रहे हैं? संग्रह में उन असमान प्रकारों की आपको आवश्यकता क्यों है? –

+0

और कक्षाएं श्रेणी और संग्रह सामान्य प्रकार हैं ... स्वयं? –

+1

@ डैनियलपर्सन इसे [उत्सुकतापूर्वक दोहराना टेम्पलेट पैटर्न] कहा जाता है (http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx) –

उत्तर

4

आप उस परिभाषा के साथ नहीं कर सकते हैं। Category और Collection (object के अलावा) के बीच कोई "सामान्य आधार वर्ग" नहीं है।

अगर वहाँ थे, कहते हैं अगर Entity<T> रूप में परिभाषित किया गया:

public class Entity 
{ 
} 

public class Entity<T> : Entity where T : Entity<T>, new() 
{ 
    public XElement ToXElement() 
    { 
    } 
    public static T FromXElement(XElement x) 
    { 
    } 
} 

तो आप

var list = new List<Entity>(); 
list.Add(new Category()); 
list.Add(new Collection()); 

कर सकता है लेकिन क्या है कि आप खरीदना चाहेंगे?

+0

मुझे बेस क्लास में FromXElement/ToXElement की आवश्यकता है। यह – Evgraf

+0

@Evgraf फिट नहीं है - तो आपको कास्ट करना होगा। 'FromXElement' विधि नहीं है जो दोनों 'श्रेणी' और' संग्रह 'दोनों लागू होते हैं (क्योंकि उनके पास अलग-अलग रिटर्न प्रकार होते हैं)। –

0

आप सभी इकाई वर्गों

public class Entity 
{ 
} 

और इकाई के वारिस इकाई

public class Entity<T> : Entity where T : Entity<T>, new() 
{ 
} 

अब आप के रूप में संस्थाओं की सूची बना सकते हैं बनाने के आधार वर्ग होने के लिए एक गैर सामान्य वर्ग को परिभाषित कर सकते हैं :

var list = new List<Entity>(); 
0

आप इस पी को हल कर सकते हैं तब

var list = new List<Entity>() 
list.Add(new Cathegory()); 

,, यदि आप एक "सामान्य विशिष्ट" आपरेशन कॉल करना चाहते हैं: वर्ग के एक गैर जेनेरिक वर्जन जोड़कर roblem

class Entity 
{ 
    // methods 

    public T As<T>() 
    { 
    if (this is T) return (T)this; 
    throw new InvalidCastException(); 
    } 
} 

class Entity<T> : Entity where T : Entity<T>, new() 

class Cathegory : Entity<T> {} 

और फिर आधार वर्ग की सूची बनाने के "As" फ़ंक्शन को कॉल करने या ऑब्जेक्ट को डालने की आवश्यकता है।

1

एक मार्कर इंटरफ़ेस बनाएँ:

public interface IAmAGenericEntity { } 

public class Entity<T> where T : IAmAGenericEntity, new() 
// ... 

public class Category : Entity<T>, IAmAGenericEntity 
// .... 

var list = new List<IAmAGenericEntity>(); 
// ... 
1

Entity पर एक abstract मार्कर की कमी से, मुझे लगता है कि To/FromXElement उपयोग प्रतिबिंब और Entity के किसी भी उप-प्रकार के लिए काम करना चाहिए। मेरा सुझाव है कि आप अपनी कक्षाओं के रूप में इस संरचना:

public class Entity 
{ 
    public XElement ToXElement() { ... } 

    protected static T FromXElement<T>(XElement x) 
     where T : Entity 
    { 
     ... 
    } 
} 

public class Category : Entity 
{ 
    public static Category : FromXElement(XElement x) 
    { 
     return FromXElement<Category>(x); 
    } 
} 

"बॉयलरप्लेट" कम से कम है, और यह की आवश्यकता नहीं है कि आप रचनात्मक प्रकार प्रणाली से बचने के। आपको किसी सामान्य आधार की कमी, या मैन्युअल रूपांतरणों के बारे में चिंता करने की ज़रूरत नहीं है।आप चाहें, तो आप बॉयलरप्लेट पूरी तरह से समाप्त कर सकते हैं और सिर्फ Entity से सीधे अपने वस्तुओं का निर्माण:

public class Entity 
{ 
    public XElement ToXElement() { ... } 

    public static T FromXElement<T>(XElement x) 
     where T : Entity 
    { 
     ... 
    } 
} 

संक्षेप में, क्या आप कर रहे हैं एक प्रकार वर्ग है, जो सी # सीधे समर्थन नहीं करता लागू कर रहा है। इस कमी के आसपास काम करने के कई तरीके हैं, लेकिन मुझे आमतौर पर उन्हें मूल्यवान होने की तुलना में अधिक परेशानी होती है, खासकर जब यह स्थिर तरीकों की बात आती है। यदि सी # स्थिर स्थिर विधियों का समर्थन करता है, तो यह आसान होगा, लेकिन हां यह नहीं है।

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