Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Renaming an interface without breaking code

Tags:

c#

.net

If I want to rename an interface without breaking existing code, would this work?

The old interface:

namespace RenameInterfaceNicely
{
    /// <summary>
    /// The old name of the interface.
    /// </summary>
    [Obsolete("IFoo is replaced by IFooNew.")]
    public interface IFoo
    {
        void Test();
    }
}

The new, renamed, interface:

namespace RenameInterfaceNicely
{
#pragma warning disable 0618
    /// <summary>
    /// IFooNew new name for the interface IFoo.
    /// </summary>
    public interface IFooNew : IFoo
    {
    }
#pragma warning restore 0618

}

So if I have a class Foo that used the old interface, that I now change to use the new interface. Will users of Foo get in trouble?

Foo before the change:

public class Foo : IFoo
{
    public void Test()
    {    
        // Do something       
        return;
    }
}

Foo after the change:

public class Foo : IFooNew
{
    public void Test()
    {    
        // Do something       
        return;
    }
}

Example of existing code:

// Old code
IFoo oldFoo = new Foo();
oldFoo.Test();
IFoo oldFoo2 = new Bar().GetFoo();

...

Bar bar = new Bar();
bar.DoSomethingWithFoo(oldFoo);

Example of new code:

// New code
IFooNew newFoo = new Foo();
newFoo.Test();
IFooNew newFoo2 = new Bar().GetFoo();

...

Bar bar = new Bar();
bar.DoSomethingWithFoo(newFoo);

My question was inspired by this one: A definitive guide to API-breaking changes in .NET and the fact that someone made a breaking change by renaming some interfaces that I was using.

like image 455
Nils Lande Avatar asked Aug 11 '26 07:08

Nils Lande


2 Answers

In the case of a genuine rename: everyone will need to recompile to pick up that change. It is a dangerous change, frankly. Interfaces are contracts, and should not be renamed. If the rename is unavoidable, however, this does at least let them know what to change it to.

--

However, actually: what you have demonstrated isn't a rename; it is a semi-compulsory extension; the IFoo still exists and still has the old features. Presumably you want people to start providing IFooNew implementations. That's reasonable, but you should aim to ensure that if a consumer only implements IFoo, then it continues to work.

like image 138
Marc Gravell Avatar answered Aug 13 '26 21:08

Marc Gravell


Renaming a public type or member is a breaking change.

  • You don't get source compatibility. Source code that explicitly mentions the interface name, it will need to be changed.
  • Depending code in the same solution can be changed automatically via rename refactoring
  • You might be able to keep binary code that depends on the interface working using Type forwarding. This has been designed for moving types between assemblies not for renaming, so I'm not sure if it works.

Deriving a new interface from the old one is still breaking:

  • When implementing a method explicitly, you need to refer to the type the method is on
  • A class implementing the old interface won't implement the new interface.
  • Code returning the old interface will still return the old interface
like image 40
CodesInChaos Avatar answered Aug 13 '26 21:08

CodesInChaos