C# interfaces with same method name
I dont know if what I'd like to do is simply not possible: or I'm not thinking about it in the correct way.
I'm trying to construct a repository interface class which accepts a generic type and uses this as the basis for the return on most of its methods, ie:
public interfac开发者_开发技巧e IRepository<T> {
void Add(T source);
T Find(int id);
}
This would then be inherited by an actual repository class, like so:
public class TestClientRepository : IRepository<ClientEmailAddress>, IRepository<ClientAccount> {
}
The idea is that within a ClientRepository, for example, I will want to perform operations against a few different object types (ClientAccount, ClientEmailAddress etc); but in the main the types of operations needed are all the same.
When I try to use the TestClientRepository (after implementing the Interfaces explicitly) I cannot see the multiple Find and Add methods.
Can anyone help? Thanks.
Sure - all you've got to do is use it as the appropriate interface:
TestClientRepository repo = new TestClientRepository();
IRepository<ClientEmailAddress> addrRepo = repo;
ClientEmailAddress address = addrRepo.Find(10);
IRepository<ClientAccount> accountRepo = repo;
ClientAccount accoutn = accountRepo.Find(5);
Basically explicitly implemented interface methods can only be called on an expression of the interface type, not on the concrete type that implements the interface.
You said:
(after implementing the Interfaces explicitly)
When you implement an interface explicitly, the only way to "see" those methods is to have the object cast to the explicitly-implemented type. So if you wanted to use it as IRepository<ClientEmailAddress>
, you'd have to cast it as such. Using it as TestClientRepository
won't let you see any explicitly-implemented methods.
Since generic parameters in inherited interfaces differ, you do not actually need the Explicit Interface Implementation for Add
.
Unfortunately the generic parameter does not influence the signature of Find
, but you can still pick one of two Find
s to be "default". For example:
interface IRepository<T> {
void Add(T source);
T Find(int id);
}
class ClientEmailAddress {
}
class ClientAccount {
}
class TestClientRepository : IRepository<ClientEmailAddress>, IRepository<ClientAccount> {
public void Add(ClientEmailAddress source) {
throw new NotImplementedException();
}
public void Add(ClientAccount source) {
throw new NotImplementedException();
}
public ClientAccount Find(int id) {
throw new NotImplementedException();
}
ClientEmailAddress IRepository<ClientEmailAddress>.Find(int id) {
throw new NotImplementedException();
}
}
// ...
var x = new TestClientRepository();
x.Find(0); // Calls IRepository<ClientAccount>.Find.
((IRepository<ClientAccount>)x).Find(0); // Same as above.
((IRepository<ClientEmailAddress>)x).Find(0); // Calls IRepository<ClientEmailAddress>.Find.
When I explicitly implemented the interface for one of the interfaces, I was not able to use the var keyword
var tcr = new TestClientRepository();
tcr. -- nothing there.
When I specified the type this works as expected.
IRepository<ClientAccount> ca = new TestClientRepository();
ca.Add(new ClientAccount { AccountName = "test2" });
IRepository<ClientEmailAddress> cea = new TestClientRepository();
cea.Add(new ClientEmailAddress { Email = "test2@test.com" });
精彩评论