Autor Beitrag
Ares
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 128



BeitragVerfasst: Mo 29.11.10 17:54 
Hallo!

Folgendes Problem:

Es sollen MP3 und JPG Dateien verwaltet werden. Hierfür gibt es die allgemeine Oberklasse File mit den spezifischen Unterklassen MP3File und JPGFile sowie die abstrakte Klasse DateiVerwalter mit den Unterklassen MP3Vewalter und JPGVerwalter.

Die Klasse DateiVerwalter macht die verwalteten Dateien als Dictionary<string, File> zugänglich:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
public class DateiVerwalter {
  // Würde zu vielen TypeCasts in Unterklassen führen:
  // protected Dictionary<string, File> files;
  // public abstract Dictionary<string, File> Files { 
  //   get { return files; }
  // }

  // Daher an dieser Stelle abstrakt und in den Unterklassen konkret
  public abstract Dictionary<string, File> Files { get; }
}


In den Unterklassen MP3Vewalter und JPGVerwalter wird sehr viel mit den spezifischen Eigenschaften von MP3File bzw. JPGFile gearbeitet. Würde daher Dictionary<string, File> files direkt in der Oberklasse DateiVerwalter definiert, wären in MP3Vewalter sehr viele Casts von File in MP3File notwendig (analog von File in JPGFile in JPGVerwalter). Daher definiere ich das Dictionary erst in den Unterlassen mit den korrekten Typen:

ausblenden 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:
public class MP3Verwalter : DateiVerwalter{
  // Würde zu vielen TypeCasts in Unterklassen führen:
  protected Dictionary<string, MP3File> mp3Files;
  
  public override Dictionary<string, File> Files { 
    // geht nicht    
    get { return mp3Files; }  
    // geht auch nicht 
    get { return (mp3Files as override Dictionary<string, File>); }
  }
}

public class JPGVerwalter : DateiVerwalter{
  // Würde zu vielen TypeCasts in Unterklassen führen:
  protected Dictionary<string, JPGFile> jpgFiles;
  
  public override Dictionary<string, File> Files { 
    // geht nicht    
    get { return jpgFiles; }  
    // geht auch nicht 
    get { return (jpgFiles as override Dictionary<string, File>); }
  }
}



Diese Casts funktionieren nicht, obwohl MP3File und JPGFile Unterklassen von File sind. Wie löst man das richtig?


Die Lösung die Dictionaries in den Unterklassen zu erstellen ist eigentlich auch nicht. Zwar hat dies wie gesagt den Vorteil, dass nicht dauernd gecasted werden muss, dafür hat man natürlich doppelt Arbeit. Im konkreten Projekt gibt es noch wesentlich mehr Dateiformate, und entsprechend mehr Unterklassen. Wie sieht also eine richtig saubere Lösung hierfür aus?

Besten Dank
Ares
Trashkid2000
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 561
Erhaltene Danke: 137



BeitragVerfasst: Mo 29.11.10 19:34 
Hallo,

könnte mir vorstellen, dass in Deinem Fall Generics ganz gut weiterhelfen würden. Denn mit einem Interface "IFile" hättest Du auch nicht wirklich Typsicherheit. Habe mit Genericss allerdings auch noch nicht so viel Erfahrung. In Deinem Beispiel würde es aber so aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
public abstract class DateiVerwalter<T> where T : File
{
  public abstract Dictionary<string, T> Files { get; }
}

Und die davon abgeleiteten Klassen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
public class MP3Verwalter : DateiVerwalter<MP3File>
{
  private Dictionary<string, MP3File> mp3Files = new Dictionary<string, MP3File>();
  public override Dictionary<string, MP3File> Files
  {
    get { return mp3Files; }
  }
}

public class JPGFileVerwalter : DateiVerwalter<JPGFile>
{
  private Dictionary<string, JPGFile> jpgFiles = new Dictionary<string, JPGFile>();
  public override Dictionary<string, JPGFile> Files
  {
    get { return jpgFiles; }
  }        
}
Denke, dass das eine saubere und typsichere Lösung ist.
LG, Marko