2

次のコード スニペットがあります。

 interface IRepositoryBase<BackupType> where BackupType : IBackup {
    IEnumerable<BackupType> Backups { get; set; }
    void Delete(BackupType backup);
    BackupType GetOrCreateBackup(IFileSource source);
  }

  interface IRepository : IRepositoryBase<IBackup> {
  }

  interface IRepository<BackupType> : IRepository, IRepositoryBase<BackupType> where BackupType : IBackup {
  }

基本的に私が持っている要求は、いくつかの IRepository<BackupType> をコレクションに入れたい場合に備えて、任意の IRepository<BackupType> を IRepository に置き換えることができるようにしたいということです (したがって、コレクションのタイプを指定できます)。それに加えて、IRepository<BackupType> が IRepository から継承されていると仮定するのは合理的で論理的だと思われます (その逆ではありません)。また、私は間違いなく IRepository に IRepository<BackupType> のすべてのプロパティとメソッドを持たせたいと思っています (唯一の違いは非ジェネリックとジェネリックです)。

残念ながら、コンパイラはコードで次のエラーを出します:

IRepository<BackupType> cannot implement both IRepositoryBase<IBackup> and IRepositoryBase<BackupType> because they may unify for some type parameter substitutions

したがって、このエラーを解消する他のコードを使用して再試行します (IRepositoryBase<> インターフェイスはなくなりました)。

  interface IRepository {
    IEnumerable<IBackup> Backups { get; set; }
    void Delete(IBackup backup);
    IBackup GetOrCreateBackup(IFileSource source);
  }

  interface IRepository<BackupType> : IRepository where BackupType : IBackup {
    new IEnumerable<BackupType> Backups { get; set; }
    void Delete(BackupType backup);
    new BackupType GetOrCreateBackup(IFileSource source);
  }

今、私はこれらの醜い「新しい」ものをそこに持っています. さらに、IRepository<BackupType> を実装すると、最初のプロパティを「new」で隠したにもかかわらず、コンパイラは両方の「Backups」プロパティを実装する必要があるようです。

誰かがこれを適切に行う方法を教えてもらえますか? :)

4

3 に答える 3

0

これはあなたが達成したいことですか?

internal class BackupType : IBackup { }

    internal interface IFileSource { }

    internal interface IBackup { }

    interface IRepository<TBackup> where TBackup : IBackup
    {
        IEnumerable<TBackup> Backups { get; set; }
        void Delete(TBackup backup);
        TBackup GetOrCreateBackup(IFileSource source);
    }

    interface IRepository : IRepository<IBackup> { }
    interface IRepositoryBackupType : IRepository<BackupType> { }

    class RepositoryBackupType:IRepository,IRepositoryBackupType
    {
    ... (implementation of both interfaces)
    }

ただし、両方のインターフェイスを実装するクラスがある場合は、型システムが基になるコレクションの変換を推測できるとは思わないため、それらを明示的に実装する必要があります。

List<IBackup> はすべての IBackup と BackupType を保持できますが、その場合、単純に IEnumerable<BackupType> にキャストすることはできません (BackupType に変換できない BackupType2 タイプが List にある可能性があるため) List<BackupType> は安全に使用できますIEnumerable<IBackup> に変換されますが、IBackup を追加することはできません (上記と同じ理由で)。

于 2013-10-17T13:36:41.640 に答える
0

あなたが行くなら:

  interface IRepositoryBase<TBackup> where TBackup : IBackup 
  {
    IEnumerable<TBackup> Backups { get; set; }
    void Delete(TBackup backup);
    TBackup GetOrCreateBackup(IFileSource source);
  }

  interface IRepository
  {
    IEnumerable<IBackup> Backups { get; set; }
    void Delete(IBackup backup);
    IBackup GetOrCreateBackup(IFileSource source);
  }

  interface IRepository<TBackup> : IRepositoryBase<TBackup>, IRepository where TBackup : IBackup 
  {
  }

コンパイラは文句を言いません。

毎回 3 つではなく 6 つのメンバーを実装する必要があり、そのうちのいくつかは明示的なインターフェイスの実装によるものです。私にはそれに対する解決策がありません。

ジェネリックを実装し、非ジェネリックも継承するため、IEnumerable<>2 つのメソッドを提供する必要がある場合も同じです。GetEnumeratorIEnumerable

于 2013-10-17T13:55:21.310 に答える