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

我正在尝试做这样的事情:

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

我收到警告:

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

还有一个错误:

以下方法或属性之间的调用不明确:’IRepository.Get(int)’和’IRepository.Get(int)’

关于如何使这种模式有效的任何想法?

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

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

请注意,您可以将其转换为一个语句:

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

……但这对我来说看起来很难看。

这涉及调用方法。 在一个类中实现两个接口是下一个障碍……因为它们在参数方面具有相同的签名。 你必须明确地实现其中至少一个 – 如果你同时做到这两点,它可能会减少混淆:

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

编辑:您还需要使用非generics方法:当前您正在尝试重新声明IRepository.Get的类型参数T 您只想使用IRepository现有类型参数。

不幸的是,你做不到。 这不是generics设计用于C#的方式。 如果你使用这种模式,你将被迫总是通过强制转换来消除你希望调用Get()接口版本的歧义:

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

这可能不是你想要的。

当然,您可以在IFooBarRepository的实现中实现代理方法,返回正确的类型……但同样,这可能不是您正在寻找的。

但是,您可以在IFooBarRepositoryIFooBarRepository可以改进语法的属性:

 interface IFooBarRepository : IRepository, IRepository { IRepository FooGetter { get; } IRepository BarGetter { get; } } 

现在你可以写:

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

通常,希望避免不接受作为类型参数类型的forms参数参数的generics方法。 在您的情况下,您尝试将存储库的语义直接编码到类型系统中。 您可能最好将此可重复性划分为表示存储库行为的类型和表示获取对象行为的单独类型。

您不需要在方法声明中再次重复T 它已经在界面上声明:

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

另请注意,您需要显式实现 IFooBarRepository接口,因为只有Get方法的返回类型不同,这是不可能的。

代替:

 Foo foo = repo.Get(1); 

使用

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

哪种方式会破坏使用generics来避免转换的总体感觉,但遗憾的是,如果不向编译器提供更多提示,那么您所做的事情是不可能的。

使用显式实现。 要指定哪个Get ,首先要转换为适当的接口。