C# 在不中断代码的情况下重命名接口
如果我想在不破坏现有代码的情况下重命名一个接口,这行得通吗 旧界面:C# 在不中断代码的情况下重命名接口,c#,.net,C#,.net,如果我想在不破坏现有代码的情况下重命名一个接口,这行得通吗 旧界面: namespace RenameInterfaceNicely { /// <summary> /// The old name of the interface. /// </summary> [Obsolete("IFoo is replaced by IFooNew.")] public interface IFoo { void T
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:
public class Foo : IFoo
{
public void Test()
{
// Do something
return;
}
}
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);
我的问题是受这个启发的:
有人通过重命名我正在使用的一些接口做了一个坏的改变。 < P>您可能想考虑将定义从<代码> IFoo <代码>复制到<代码> IFOONEW < /代码>,而不是将它作为子接口实现。这可能会使以后更容易删除
IFoo
,尤其是当有人显式实现该接口时
考虑以下几点:
public class Foo : IFoo {
void IFoo.Test() {}
}
升级到新版本(v2)后,他们现在会收到您的过时的
编译器警告,希望在某个时候,他们会进行更改,以实现IFooNew
而不是IFoo
,并更改所有引用。但是因为他们使用显式实现,所以必须将实现保留为IFoo.Test
,而不是IFooNew.Test
:
public class Foo : IFooNew {
void IFoo.Test() {}
}
他们不再收到编译器警告,一切正常。在库的下一个版本(v3)中,您将Test
方法移动到IFooNew
,消除IFoo
,现在他们再次升级到您的最新版本-他们现在必须再次更改代码
public class Foo : IFooNew {
void IFooNew.Test() {}
}
理想情况下,您只能强制他们更改代码一次,而不是两次。重命名公共类型或成员是一个突破性的更改
- 您无法获得源代码兼容性。如果源代码明确提到接口名称,则需要对其进行更改
- 同一解决方案中的依赖代码可以通过重命名重构自动更改
- 您可能能够保留依赖于使用的接口的二进制代码。这是为在程序集之间移动类型而设计的,不是为了重命名,所以我不确定它是否有效
- 显式实现方法时,需要引用该方法所在的类型
- 实现旧接口的类不会实现新接口
- 返回旧接口的代码仍将返回旧接口
然而,事实上:您所演示的不是重命名;这是一种半强制性的延伸;
IFoo
仍然存在,并且仍然具有旧的功能。大概您希望人们开始提供IFooNew
实现。这是合理的,但您应该确保如果消费者仅实现IFoo
,那么它将继续工作。我们不能不知道类型是如何使用的。这有可能破坏一个程序吗,是的。您对任何公共API所做的任何类型的更改在某种程度上、形状或形式上都是破坏性的更改。如果接口在语义上相同,但在技术上不相关,则无法将实现新接口的对象传递给任何期望旧接口的方法,反之亦然。对于一个广泛分布的库来说,这几乎肯定是不可能的,而且是一个比OP的方法更具破坏性的变化。@Servy也许我误解了。我的印象是,旧的界面最终会被删除,在这种情况下,是的,你绝对会在某个时候造成巨大的破坏性变化,并迫使人们将所有代码切换到你的新界面,以便升级。在这种情况下,我宁愿进行一轮变革,也不愿进行两轮变革。但是,如果原始接口将永远存在,那么我同意你的观点,并将不使用它。我的想法是将Test()方法保留在旧接口中,以便现有代码可以工作。旧界面的所有用户在编译代码时当然会收到警告。我还考虑了一个场景,在这个场景中,可以通过删除IFoo接口并将Test()-方法移动到新接口IFooNew中,在更高版本中(在用户有机会修复代码之后)进行制动更改。