开发者

C# interfaces with same method name

开发者 https://www.devze.com 2023-04-07 05:07 出处:网络
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 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 Finds 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" });
0

精彩评论

暂无评论...
验证码 换一张
取 消