2009-08-12 11 views
24

मैं List<ObjBase> को List<Obj> के रूप में क्यों नहीं डाल सकता? काम क्यों नहीं निम्नलिखित है:सी # सूची <ObjBase> सूची के रूप में <Obj>

internal class ObjBase 
    { 
    } 

internal class Obj : ObjBase 
    { 
    } 

internal class ObjManager 
{ 
    internal List<Obj> returnStuff() 
    { 
     return getSomeStuff() as List<Obj>; 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 

} 

इसके बजाय मैं यह करने के लिए है:

internal class ObjBase 
    { 
    } 

internal class Obj : ObjBase 
    { 
    } 

internal class ObjManager 
{ 
    internal List<Obj> returnStuff() 
    { 
     List<ObjBase> returnedList = getSomeStuff(); 
     List<Obj> listToReturn = new List<Obj>(returnedList.Count); 
     foreach (ObjBase currentBaseObject in returnedList) 
     { 
      listToReturn.Add(currentBaseObject as Obj); 
     } 
     return listToReturn; 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 
} 

मैं विजुअल स्टूडियो 2008 में निम्न त्रुटि (पठनीयता के लिए छोटा):

नहीं कर सकते एक संदर्भ रूपांतरण, मुक्केबाजी रूपांतरण, अनबॉक्सिंग रूपांतरण, रैपिंग रूपांतरण, या शून्य प्रकार रूपांतरण के माध्यम से 'सूची' में 'सूची' को रूपांतरित करें

धन्यवाद।

+0

-1:

var x = new List<ObjBase>(); var y = x.CastList<ObjBase, Obj>(); // y is now an IList<Obj> 

कोड अपनी लाइब्रेरी में जोड़ने के लिए यहाँ कई सवाल का Dup, सहित http://stackoverflow.com/questions/1263489/how- do-i-upcast-a-collection-of-base-class-in-c/1263514 # 1263514 और –

+0

नीचे दिए गए उत्तर में उद्धृत किए गए लोगों [.NET कास्टिंग जेनेरिक सूची] का संभावित डुप्लिकेट (http://stackoverflow.com/प्रश्न/674715/नेट-कास्टिंग-जेनेरिक-सूची) –

उत्तर

1

मुझे लगता है कि आप जिस कलाकार को करने की कोशिश कर रहे हैं उसे गलत समझ रहे हैं। आप सोच रहे हैं कि आप सूची में संग्रहीत ऑब्जेक्ट के प्रकार को बदल रहे हैं, जहां आप वास्तव में सूची के प्रकार को बदलने की कोशिश कर रहे हैं। यह समझ में आता है कि आप सूची को स्वयं नहीं बदल सकते हैं क्योंकि आप इसे पहले ही पॉप्युलेट कर चुके हैं।

आप इसे बेस क्लास की सूची के रूप में देख सकते हैं और फिर जब आप सूची आइटम को संसाधित कर रहे हैं तो इसे कास्ट करें, यह मेरा दृष्टिकोण होगा।

इस प्रयास किए गए कलाकार का उद्देश्य क्या है?

0

Linq एक ConvertAll विधि है। तो

list.ConvertAll<Obj>(objBase => objbase.ConvertTo(obj)); 

मुझे कुछ और सुझाव देना नहीं है। मुझे लगता है कि ओब्जेबेस बेस क्लास है, और यदि सभी ओब्जेबेस ऑब्जेक्ट ओब्जे ऑब्जेक्ट्स हैं, तो मुझे यकीन नहीं है कि आपके पास पहली जगह क्यों दो वस्तुएं होंगी। शायद मैं निशान से बाहर हूँ।

संपादित करें: सूची। कैस्ट विधि उपर्युक्त से बेहतर काम करेगी, मान लीजिए कि वे एक दूसरे के लिए जाति योग्य हैं। इसके बारे में भूल गए जब तक कि मैं अन्य उत्तरों को पढ़ता हूं।

9

पर देखो मैं केवल एक जावा देखने से "समस्या" वर्णन कर सकते हैं, लेकिन थोड़ी से मैं जानता हूँ कि इस पहलू दोनों सी # और जावा में एक ही है:

एक List<ObjBase> एक List<Obj> नहीं है, क्योंकि इसमें ObjBase ऑब्जेक्ट हो सकता है जो Obj ऑब्जेक्ट नहीं है।

एक List<Obj> दूसरी तरह के आसपास नहीं एक List<ObjBase> लिए डाली जा सकती है, पूर्व की गारंटी देता है एक ObjBase तर्क है, जो बाद स्वीकार नहीं करेंगे के साथ एक Add() कॉल स्वीकार करने के लिए है क्योंकि!

तो संक्षेप में प्रस्तुत करने के लिए: भले ही एक Obj है-एक ObjBase एक List<Obj> एक List<ObjBase>नहीं है।

+0

यह मैंने पढ़े गए सामान्य कॉन्वर्सेट समस्या का सबसे सरल वर्णन है। अच्छा लगा। –

1

सी # वर्तमान में जेनेरिक प्रकारों के लिए भिन्नता का समर्थन नहीं करता है। मैंने जो पढ़ा है, उससे 4.0 में बदल जाएगा।

जेनिक्स में भिन्नता के बारे में अधिक जानकारी के लिए here देखें।

32

आप Cast और ToList सिस्टम से विस्तार विधियों का उपयोग कर सकते हैं। लिंकक इसे एक पंक्ति में रखने के लिए।

internal List<Obj> returnStuff() 
{ 
    return getSomeStuff() as List<Obj>; 
} 

के बजाय ऐसा करते हैं:

internal List<Obj> returnStuff() 
{ 
    return getSomeStuff().Cast<Obj>().ToList(); 
} 
0

यह सी # में एक प्रमुख दर्द है - यह कैसे जेनरिक डिजाइन किए गए थे है। सूची सूची का विस्तार नहीं करती है, यह सिर्फ एक पूरी तरह से अलग प्रकार है। आप किसी भी तरह से उन्हें एक-दूसरे को नहीं डाल सकते हैं या असाइन नहीं कर सकते हैं, आपका एकमात्र विकल्प एक सूची को दूसरी सूची में कॉपी करना है।

0

Lazarus:
मैंने सोचा था कि संकलक एहसास होता है कि मैं और सूची की वस्तुओं पर किया कार्यों चाहता था नहीं मैं स्वयं सूची कास्ट करने के लिए कोशिश कर रहा था कि।

कुछ अधिक जानकारी:

public abstract class ObjBase 
    { 
    } 

internal interface IDatabaseObject 
    { 
    } 

public class Obj : ObjBase, IDatabaseObject 
    { 
    } 


internal interface IDatabaseObjectManager 
    { 
     List<ObjBase> getSomeStuff(); 
    } 

public class ObjManager : IObjManager 
{ 
    public List<Obj> returnStuff() 
    { 
     return getSomeStuff().Cast <Customer>().ToList<Customer>(); 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 
} 

अब इस DLL के बाहर ग्राहक कोड जा सकते हैं: ObjManager objM = नए ObjManager(); सूची सूची ओबी = objM.returnStuff(); मैं आवेदन के इस भाग (ओ/आरएम) के लिए कई Obj और ObjManager प्रकार बनाने जा रहा हूं।

(अरे टिप्पणी ब्लॉक पात्रों से बाहर भाग! :-)

0

यहाँ है कि कैसे मैं एक

करने के लिए एक

object 

करने के लिए एक

list<SomeOtherObject> 

से रूपांतरण तय की और उसके बाद

List<object> 

https://stackoverflow.com/a/16147909/2307326

1

सूची.कॉन्टर सभी आकर्षक लग रहा है लेकिन 1 बड़ा नुकसान है: यह एक पूरी नई सूची तैयार करेगा। यह विशेष रूप से बड़ी सूचियों के लिए प्रदर्शन और स्मृति उपयोग को प्रभावित करेगा।

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

उपयोग:

public static class Extensions 
{ 
    public static IList<TTo> CastList<TFrom, TTo>(this IList<TFrom> list) 
    { 
     return new CastedList<TTo, TFrom>(list); 
    } 
} 

public class CastedList<TTo, TFrom> : IList<TTo> 
{ 
    public IList<TFrom> BaseList; 

    public CastedList(IList<TFrom> baseList) 
    { 
     BaseList = baseList; 
    } 

    // IEnumerable 
    IEnumerator IEnumerable.GetEnumerator() { return BaseList.GetEnumerator(); } 

    // IEnumerable<> 
    public IEnumerator<TTo> GetEnumerator() { return new CastedEnumerator<TTo, TFrom>(BaseList.GetEnumerator()); } 

    // ICollection 
    public int Count { get { return BaseList.Count; } } 
    public bool IsReadOnly { get { return BaseList.IsReadOnly; } } 
    public void Add(TTo item) { BaseList.Add((TFrom)(object)item); } 
    public void Clear() { BaseList.Clear(); } 
    public bool Contains(TTo item) { return BaseList.Contains((TFrom)(object)item); } 
    public void CopyTo(TTo[] array, int arrayIndex) { BaseList.CopyTo((TFrom[])(object)array, arrayIndex); } 
    public bool Remove(TTo item) { return BaseList.Remove((TFrom)(object)item); } 

    // IList 
    public TTo this[int index] 
    { 
     get { return (TTo)(object)BaseList[index]; } 
     set { BaseList[index] = (TFrom)(object)value; } 
    } 

    public int IndexOf(TTo item) { return BaseList.IndexOf((TFrom)(object)item); } 
    public void Insert(int index, TTo item) { BaseList.Insert(index, (TFrom)(object)item); } 
    public void RemoveAt(int index) { BaseList.RemoveAt(index); } 
} 

public class CastedEnumerator<TTo, TFrom> : IEnumerator<TTo> 
{ 
    public IEnumerator<TFrom> BaseEnumerator; 

    public CastedEnumerator(IEnumerator<TFrom> baseEnumerator) 
    { 
     BaseEnumerator = baseEnumerator; 
    } 

    // IDisposable 
    public void Dispose() { BaseEnumerator.Dispose(); } 

    // IEnumerator 
    object IEnumerator.Current { get { return BaseEnumerator.Current; } } 
    public bool MoveNext() { return BaseEnumerator.MoveNext(); } 
    public void Reset() { BaseEnumerator.Reset(); } 

    // IEnumerator<> 
    public TTo Current { get { return (TTo)(object)BaseEnumerator.Current; } } 
} 
संबंधित मुद्दे