在不破坏代码的情况下重命名接口

本文关键字:情况下 重命名 接口 代码 | 更新日期: 2023-09-27 18:17:36

如果我想重命名一个接口而不破坏现有的代码,这会工作吗?

旧接口:

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的用户会遇到麻烦吗?

修改前:

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);

我的问题是受这个启发的:关于。net中api破坏变化的权威指南而且有人做了一个突破性的改变,重命名了我正在使用的一些界面

在不破坏代码的情况下重命名接口

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

,

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

重命名公共类型或成员是一个破坏性的更改。

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

从旧接口派生一个新接口仍然是坏的:

  • 当显式实现一个方法时,你需要在
  • 中引用该方法的类型
  • 实现旧接口的类不能实现新接口。
  • 返回旧接口的代码仍将返回旧接口

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

考虑以下内容:

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

升级到你的新版本(v2)后,他们现在会得到你的Obsolete编译器警告,在某种程度上,希望他们会改变,所以他们实现IFooNew而不是IFoo,并改变所有引用。但是由于他们使用显式实现,他们必须将实现保留为IFoo.Test而不是IFooNew.Test:

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

它们不再得到编译器警告,一切都很好。在库的下一个版本(v3)中,您将Test方法移到IFooNew中,消除IFoo,现在它们再次升级到您的最新版本-它们现在必须再次更改代码。

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

理想情况下,你只会强迫他们修改一次代码而不是两次。