代码之家  ›  专栏  ›  技术社区  ›  Jonas

实现多个通用接口-类型错误

  •  4
  • Jonas  · 技术社区  · 14 年前

    public interface IRepository<T>
    {
      T Get<T>(int id);
    }
    
    public interface IFooBarRepository : IRepository<Foo>, IRepository<Bar>
    {
    }
    
    IFooBarRepository repo = SomeMethodThatGetsTheActualClass();
    Foo foo = repo.Get<Foo>(1);
    

    我得到一个警告:

    类型参数“T”与外部类型“IRepository”中的类型参数同名

    以下方法或属性之间的调用不明确:'我相信。快(int)“和”我相信。快(内景)

    有什么想法我可以让这个模式工作吗?

    5 回复  |  直到 14 年前
        1
  •  7
  •   Jon Skeet    14 年前

    要调用适当的表达式,需要让编译器以适当的方式考虑表达式:

    IFooBarRepository repo = SomeMethodThatGetsTheActualClass();
    IRepository<Foo> fooRepo = repo;
    Foo foo = fooRepo.Get(1);
    

    就用一句话来说:

    IFooBarRepository repo = SomeMethodThatGetsTheActualClass();
    Foo foo = ((IRepository<Foo>)repo).Get(1);
    

    ... 但我觉得很难看。

    处理 打电话 方法。 实施 一个类中的两个接口是下一个障碍。。。因为它们在参数上有相同的签名。您必须显式地实现其中至少一个,如果同时实现这两个功能,可能会减少混淆:

    public class FooBarRepository : IFooBarRepository
    {
        Foo IRepository<Foo>.Get(int id)
        {
            return new Foo();
        } 
    
        Bar IRepository<Bar>.Get(int id)
        {
            return new Bar();
        } 
    }
    

    编辑:你还需要 Get 非泛型方法:当前您正尝试重新声明类型参数 T 在里面 IRepository<T>.Get<T> ;您只想使用 现有的 的类型参数 IRepository<T>

        2
  •  3
  •   LBushkin    14 年前

    这不是泛型在C#中工作的方式。如果使用这种模式,您将被迫始终消除希望调用的接口版本的歧义 Get() 铸造 repo :

    IFooBarRepository repo = SomeMethodThatGetsTheActualClass(); 
    Foo foo = ((IRepository<Foo>)repo).Get(1); 
    

    当然,您可以在 IFooBarRepository 返回正确的类型。。。不过,这可能不是你想要的。

    但是,可以在上创建属性 IFooBarRepository公司

    interface IFooBarRepository : IRepository<Foo>, IRepository<Bar>
    {
        IRepository<Foo> FooGetter { get; }
        IRepository<Bar> BarGetter { get; }
    }
    

    现在你可以写:

    IFooBarRepository repo = SomeMethodThatGetsTheActualClass(); 
    Foo foo = repo.FooGetter.Get(1); 
    Bar bar = repo.BarGetter.Get(2);
    

        3
  •  2
  •   Darin Dimitrov    14 年前

    你不需要重复 T 再次在方法声明处。它已在接口上声明:

    public interface IRepository<T>
    {
        T Get(int id);
    }
    

    同时请注意,您需要 explicitly implement IFooBarRepository 接口,因为只有Get方法的返回类型不同,这是不可能的。

        4
  •  1
  •   x0n    14 年前

    Foo foo = repo.Get<Foo>(1);
    

    使用

    Foo foo = ((IRepository<Foo>)repo).Get(1);
    

    避免

        5
  •  0
  •   Steven Sudit    14 年前

    使用显式实现。指定 Get ,首先向上转换到适当的接口。