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,以防我想将一些 IRepository<BackupType> 放入一个集合中(这样我就可以为集合指定一个类型)。此外,假设 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> 后,编译器似乎仍然希望实现两个“Backups”属性,尽管我用“new”隐藏了第一个属性。

有人可以告诉我如何正确地做到这一点吗?:)

4

3 回答 3

3

如果你看看微软是如何实现的List<T>,你会发现他们没有继承接口。您可以将 aList<T>同时视为 anIList和 a的唯一原因IList<T>是因为List<T>实现了它们。

您可能想要的是显式地实现非泛型接口。这是隐式实现和显式实现之间的区别:

// Implicit
public IEnumerable<TapeBackup> Types { get; set; }

// Explicit
IEnumerable<IBackup> IRepository.Types { get; set; }

显式接口实现隐藏在程序集元数据中并且不可访问,除非您首先将实例转换为适当的接口类型。您只需将显式实现包装并调用隐式实现,因为类型很可能兼容。

但是我认为您无法实现为两个接口仅实现一次成员的目标。

于 2013-10-17T13:39:54.710 回答
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 
  {
  }

编译器不会抱怨。

您仍然必须每次都实现六个成员而不是三个成员,其中一些成员通过显式接口实现。我对此没有解决方案。

当您实现 genericIEnumerable<>并且必须提供两种GetEnumerator方法时也是如此,因为您也继承了 non-generic IEnumerable

于 2013-10-17T13:55:21.310 回答
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>(因为 List 中可能存在无法转换为 BackupType 的 BackupType2 类型) List<BackupType> 可以安全转换为 IEnumerable<IBackup>,但是您不能只向其中添加 IBackup(出于与上述相同的原因)。

于 2013-10-17T13:36:41.640 回答