重命名接口而不破坏代码

时间:2014-08-12 18:10:48

标签: c# .net

如果我想在不破坏现有代码的情况下重命名界面,这会有用吗?

旧界面:

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

新的,重命名的界面:

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

}

因此,如果我有一个使用旧接口的类Foo,我现在改为使用新接口。 Foo的用户会遇到麻烦吗?

改变前的Foo:

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

Foo:

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

现有代码示例:

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

...

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

新代码示例:

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

...

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

我的问题受到了这个问题的启发: A definitive guide to API-breaking changes in .NET 而且有人通过重命名我正在使用的某些接口来进行重大改变。

3 个答案:

答案 0 :(得分:2)

在真正重命名的情况下:每个人都需要重新编译以获取该更改。坦率地说,这是一个危险的变化。接口是合同,不应重命名。但是,如果重命名是不可避免的,那么至少让他们知道要将其更改为什么。

-

然而,实际上:您所演示的不是重命名;这是一个半强制性的延伸; IFoo仍然存在且仍具有旧功能。大概你希望人们开始提供IFooNew实现。这是合理的,但您应该确保如果消费者实施IFoo,那么它将继续有效。

答案 1 :(得分:0)

重命名公共类型或成员是一个重大改变。

  • 您没有获得源兼容性。明确提到接口名称的源代码,需要更改。
  • 可以通过重命名重构自动更改同一解决方案中的代码
  • 您可以保留依赖于使用Type forwarding工作的界面的二进制代码。这个设计用于在程序集之间移动类型而不是重命名,因此我不确定它是否有效。

从旧的界面中获取新界面仍在破坏:

  • 明确实现方法时,需要引用方法所在的类型
  • 实现旧接口的类不会实现新接口。
  • 返回旧界面的代码仍将返回旧界面

答案 2 :(得分:-1)

您可能需要考虑将定义从IFoo复制到IFooNew,而不是将其作为子接口实现。这可能会使以后更容易删除IFoo,特别是如果有人明确实现了接口。

请考虑以下事项:

public class Foo : IFoo {
    void IFoo.Test() {}
}

升级到新版本(v2)后,他们现在会收到Obsolete编译器警告,并且在某些时候,希望他们会更改,以便他们实施IFooNew而不是{{1}并更改所有引用。但由于他们使用显式实现,他们必须将实现保留为IFoo而不是IFoo.Test

IFooNew.Test

他们不再收到编译器警告,一切都很好。在您的库的下一个版本(v3)中,您将public class Foo : IFooNew { void IFoo.Test() {} } 方法移至Test,消除IFooNew,现在他们再次升级到您的最新版本 - 他们现在必须更改其代码试。

IFoo

理想情况下,您只会强制他们更改一次代码而不是两次。