簡體   English   中英

重命名接口而不破壞代碼

[英]Renaming an interface without breaking code

如果我想在不破壞現有代碼的情況下重命名接口,這會有用嗎?

舊界面:

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

我的問題受到了這個問題的啟發: 對.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() {}
}

理想情況下,您只會強制他們更改一次代碼而不是兩次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM