2012-04-15 14 views
5

私の問題は次のとおりです。私は明らかに動作していない家庭プロジェクトのコードデザインを作成しました。たぶんあなたは私が "コードのにおい"がどこから来るのか理解するのを助けることができます。抽象的なジェネリック型変数の宣言

もOKですが、始めましょう: 私はアーカイブの種類の周りの異なる種類のラップするためにいくつかのクラスを定義している:これらのアーカイブを処理するために

public abstract class Archive { } 
public class ZipArchive : Archive { } 
public class TarArchive : Archive { } 

を、私はマネージャークラスを定義しました。今、何が起こる

public class ZipArchiveManager : ArchiveManager<ZipArchive> 
{ 
    public override void OpenArchive(ZipArchive archive) { /* .. */ } 
} 

public class TarArchiveManager : ArchiveManager<TarArchive> 
{ 
    public override void OpenArchive(TarArchive archive) { /* .. */ } 
} 

コンパイル時に、私はどのようなものを知らないということです。実際には、特定のbehaiourを実装すること 必要な動作を定義する抽象1、

public abstract class ArchiveManager<T> where T : Archive 
{ 
    public abstract void OpenArchive(T archive); 
} 

とコンクリートのもの、私が処理するのアーカイブので、私は次のことを試してみました:

次のエラーで終わった
class Program 
{ 
    static void Main(string[] args) 
    { 
     ArchiveManager<Archive> archiveManager = null; 

     if (/*some condition*/) {    
      archiveManager = new ZipArchiveManager(); 
     } 
     else { 
      archiveManager = new TarArchiveManager(); 
     } 
    } 
} 

私が理解する限り、総称引数を暗黙的に変換することはできません。これを回避する方法はありますか?このコード/デザインは "匂い"ですか?

ありがとうございます。

+0

作成し、C#の.NET 4.0の「ダイナミック」キーワードを使用して、別の方法...私にとっては魔法のように

class Program { static void Main(string[] args) { dynamic archiveManager = null; if (/*some condition*/) { archiveManager = new ZipArchiveManager(); } else { archiveManager = new TarArchiveManager(); } } } 

作品を見つけました一般的ではないベースクラスを使用するか、共変インタフェースを使用します。 – CodesInChaos

+1

また、OpenArchiveの署名が間違っています。ストリームを受け取って、 'T'を返すべきではありませんか? – CodesInChaos

答えて

2

機能を実装していない抽象クラスではなく、反動的なインターフェイスを使用できます。この場合は、あなただけではない引数として、メソッドの戻り値としてtypeパラメータを使用することができます。

public interface IArchiveManager<out T> 
    where T : Archive 
{ 
    T OpenArchive(Stream stream); 
} 

その後、単にあなたのマネージャークラスのインターフェイスを実装しています

public class ZipArchiveManager : IArchiveManager<ZipArchive> 
{ 
    public ZipArchive OpenArchive(Stream stream) 
    { 
     // ... 
    } 
} 

public class TarArchiveManager : IArchiveManager<TarArchive> 
{ 
    public TarArchive OpenArchive(Stream stream) 
    { 
     // ... 
    } 
} 
+0

ありがとうございました。これを克服する唯一の方法は、コントラストバリアントインターフェースです。しかし、私は私のアーキテクチャ全体を再考する必要があると信じています... :( – Flagg1980

0

私は)

+0

'dynamic'を使うことの欠点は静的型チェックを失うことです。メソッド名、メソッドシグネチャ、コンパイラは 'dynamic'型に対してこれをキャッチしません。 – Michael

関連する問題