Entwickler-Ecke

C# - Die Sprache - Liste casten


winx - Do 15.12.05 17:08
Titel: Liste casten
Hi,

ich habe folgendes Problem:

Ich habe 3 Interfaces die wie folht aussehen:

C#-Quelltext
1:
2:
3:
4:
5:
ISuper

IChild1 : ISuper

IChild2 : ISuper

Nun habe ich eine Klasse die eine Liste der ISuper Objekte enthält

C#-Quelltext
1:
public void getNumber(list<ISuper>)...                    


Ist es mir irgendwie möglich diese Funktion durch übergeben mit einer Liste der IChild1 oder IChild2 Objekte aufzurufen
sprich

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
void test
{
   ...
   list<IChild1> liste = new list<IChild1>;
   obj.getNumber(liste);

}


Irgendwie müsste jedes Elemet casten lassen...ist dies auch automatisch möglich, da ja das Interface
IChild1 die Schnitstelle ISuper besitzt???

Danke


Motzi - Do 15.12.05 18:37

Nein, das geht so nicht. List<ISuper> und List<IChild1> haben keine Vererbungsbeziehung (auch wenn es zwischen ISuper und IChild1 einegibt), da C# nur F-gebundene Generizität unterstützt.


Robert_G - Do 15.12.05 22:57

user profile iconwinx hat folgendes geschrieben:
Irgendwie müsste jedes Elemet casten lassen...ist dies auch automatisch möglich, da ja das Interface
IChild1 die Schnitstelle ISuper besitzt???
Nein.
List<IChild> erbt ja nicht von List<ISuper> (Wie Motzi bereits schrieb)

Es gibt sicher 5.000 Möglichkeiten dafür, ich habe mal ein paar Bleistifte runtergetippt. Vllt hilft's dir.

Falls GetNumber[meta]dumm benannt btw, da ein void nie GetXXX heißen sollte[/meta] wirklich einen Eintrag anhand einer Nummer finden sollte, wäre hier eines der Dictionaries das Mittel der Wahl. ;)



C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
interface ISuper
{
  int Id { get;}
}

interface IChild : ISuper
{
  string Name { get;}
}

class Super : ISuper
{
  int id;

  public int Id
  {
    get { return id; }
  }

  public Super(int id)
  {
    this.id = id;
  }

  public static TReturn FindById<TInput, TReturn>(IEnumerable<TInput> list, int id)
    where TInput  : ISuper
    where TReturn : TInput
  {
    foreach (TInput item in list)
    {
      if (item is TReturn && id.Equals(item.Id))
      {
        return (TReturn)(item);
      }
    }
    return default(TReturn);
  }
}

class Child : Super, IChild
{
  string name;

  public string Name
  {
    get { return name; }
    set { name = value; }
  }

  public Child(int id, string name)
    : base(id)
  {
    this.name = name;
  }
}

class Decorator<TInput, TReturn> : IEnumerable<TReturn>
where TReturn : TInput
{
  readonly IEnumerable<TInput> innerInstance;

  protected IEnumerable<TInput> InnerInstance
  {
    get { return innerInstance; }
  }

  public Decorator(IEnumerable<TInput> innerInstance)
  {
    this.innerInstance = innerInstance;
  }

  #region IEnumerable<T> Members

  public IEnumerator<TReturn> GetEnumerator()
  {
    foreach (TInput item in innerInstance)
    {
      if (item is TReturn)
        yield return (TReturn)item;
    }
  }

  #endregion

  #region IEnumerable Members

  IEnumerator IEnumerable.GetEnumerator()
  {
    return innerInstance.GetEnumerator();
  }

  #endregion
}



class Program
{
  static void Main(string[] args)
  {
    List<ISuper> list = new List<ISuper>();

    for (int i = 0; i < 10; i++)
    {
      list.Add(new Super(i));
      list.Add(new Child(i, i.ToString()));
    }

    int searchId = 2;

    IChild child;

    // cast auf IChild
    child = (IChild)list.Find(delegate(ISuper item)
                                      {
                                        return item is IChild &&
                                               item.Id == searchId;
                                      });

    // generic Method in deiner Klasse
    child = Super.FindById<ISuper, IChild>(list, 2);

    // Kopie des Containers, typisiert auf IChild
    List<IChild> childList = list.ConvertAll<IChild>(delegate(ISuper input)
                                                             {
                                                               if (input is IChild)
                                                                 return (IChild)input;
                                                               else
                                                                 return null;
                                                             });


    child = childList.Find(delegate(IChild item)
                                    {
                                      return item != null &&
                                             item.Id == searchId &&
                                             item.Name == searchId.ToString();
                                    });

    // Ein Dekorator, der dir eine auf IChild gefilterte Ansicht gibt
    Decorator<ISuper, IChild> childDecorator = new Decorator<ISuper, IChild>(list);

    foreach (IChild item in childDecorator)
    {
      Console.WriteLine(item.Name);
    }
  }
}