6

I have this interface:

public interface INameScope
{
    void Register(string name, object scopedElement);
    object Find(string name);
    void Unregister(string name);
}

But I want my implementation have different names for the methods. My implementation already has a Register method that has another meaning.

Isn't there a method to make implemented methods have names like "RegisterName", "FindName" or "UnregisterName" instead of having to use the very same names?

SuperJMN
  • 13,110
  • 16
  • 86
  • 185
  • Why not change the interface? – D. Ben Knoble Aug 27 '15 at 12:04
  • Because... https://msdn.microsoft.com/en-us/library/system.windows.markup.inamescope(v=vs.110).aspx – SuperJMN Aug 27 '15 at 12:08
  • Ah my bad. It was unclear that you couldn't adjust the interface from the question. – D. Ben Knoble Aug 27 '15 at 14:55
  • 1
    I just hit this problem today in C#. What's driving me nuts about it is that this is available in Visual Basic (which I used at previous jobs): `Public Function MyCustomRegisterMethod() Implements INameScope.Register`. The accepted answer isn't good enough for me, since the functionality depends on whether I treat it as an interface or concrete type. Similar to shadowing: http://stackoverflow.com/questions/392721/difference-between-shadowing-and-overriding-in-c – ps2goat Oct 18 '16 at 21:12

2 Answers2

10

Not quite, but you can use explicit interface implementation:

public class SomeScope : INameScope
{
    void INameScope.Register(string name, object scopedElement)
    {
        RegisterName(name, scopedElement);
    }

    public void Register(...)
    {
        // Does something different
    }

    public void RegisterName(...)
    {
        // ...
    }

    ...
}

I would be very wary of doing this if your existing Register method has similar parameters though - while the compiler will be happy with this, you should ask yourself how clear it's going to be to anyone reading your code:

SomeScope x = new SomeScope(...);
INameScope y = x;
x.Register(...); // Does one thing
y.Register(...); // Does something entirely different
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Yes, I know what you mean. Maybe there should be a hosting class with a namescope (association) and exposing its methods like public RegisterName(...) { namescope.Register(... ) }. It's more a design concern, then? – SuperJMN Aug 27 '15 at 12:05
  • 1
    @SuperJMN: Yes, that would make a lot of sense - except that you couldn't then use your existing class for anything expecting an `INameScope`. – Jon Skeet Aug 27 '15 at 12:07
  • Nice point, Jon. But this still looks like a major bummer for me. Interface names force implementors keep the names, either meaningful or not... – SuperJMN Aug 27 '15 at 12:12
5

Binding of method implementations to interface methods that they implement is done by method signature, i.e. the name and the parameter list. The class that implements an interface with a method Register must have a method Register with the same signature. Although C# lets you have a different Register method as an explicit implementation, in situations like that a better approach would be to go for the Bridge Pattern, which lets you "connect" an interface to an implementation with non-matching method signatures:

interface IMyInterface {
    void Register(string name);
}

class MyImplementation {
    public void RegisterName(string name) {
        // Wrong Register
    }
    public void RegisterName(string name) {
        // Right Register
    }
}

The bridge class "decouples" MyImplementation from IMyInterface, letting you change names of methods and properties independently:

class MyBridge : IMyInterface {
    private readonly MyImplementation impl;
    public MyBridge(MyImplementation impl) {
        this.impl = impl;
    }
    public void Register(string name) {
        impl.RegisterName();
    }
}

When make changes to one of the sides of the bridge, you need to make the corresponding change in the bridge to be back in business.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • OK, but as you could see, with the bridge, you're not changing he name of the invoked method. In the interface it's called "Register", the same name it has in the bridge. What I want is to implement it with a different name. – SuperJMN Aug 28 '15 at 09:36
  • 1
    @SuperJMN The bridge lets `MyImplementation` pretend that it implements `IMyInterface` without actually implementing it. The bridge implements the interface with the matching names to keep C# happy, but the "payload" logic of the implementation comes from `MyImplementation` class. The bridge class simply forwards the calls, while `MyImplementation` does all the work and keeps all the state. – Sergey Kalinichenko Aug 28 '15 at 10:04