影響相容性的變更Changes that affect compatibility

縱觀其歷程記錄,.NET 一直嘗試維護 .NET 各版本之間以及各種變體之間的相容性。Throughout its history, .NET has attempted to maintain a high level of compatibility from version to version and across flavors of .NET. 在 .NET Core 中仍是如此。This continues to be true for .NET Core. 雖然 .NET Core 可以視為是獨立於 .NET Framework 之外的新技術,但是有兩個主要因素限制了 .NET Core 從 .NET Framework 分離的能力:Although .NET Core can be considered as a new technology that is independent of the .NET Framework, two major factors limit the ability of .NET Core to diverge from .NET Framework:

  • 最初開發或是繼續開發 .NET Framework 應用程式的大量開發人員。A large number of developers either originally developed or continue to develop .NET Framework applications. 他們預期跨 .NET 實作有一致的行為。They expect consistent behavior across .NET implementations.

  • .NET Standard 程式庫專案可讓開發人員建立以 .NET Core 和 .NET Framework 所共用之通用 API 為目標的程式庫。.NET Standard library projects allow developers to create libraries that target common APIs shared by .NET Core and .NET Framework. 開發人員預期 .NET Core 應用程式中使用之程式庫的行為,應與 .NET Framework 應用程式中所使用的程式庫相同。Developers expect that a library used in a .NET Core application should behave identically to the same library used in a .NET Framework application.

除了 .NET 實作之間的相容性之外,開發人員還希望 .NET Core 版本之間具有高層級相容性。Along with compatibility across .NET implementations, developers expect a high level of compatibility across .NET Core versions. 特別是,針對較早版本的 .NET Core 所撰寫的程式碼應該在新版的 .NET Core 上順暢地執行。In particular, code written for an earlier version of .NET Core should run seamlessly on a later version of .NET Core. 實際上,許多開發人員預期在新發行的 .NET Core 版本中找到的新 API,也應該與引入那些 API 的發行前版本相容。In fact, many developers expect that the new APIs found in newly released versions of .NET Core should also be compatible with the pre-release versions in which those APIs were introduced.

此文章概述相容性變更 (或中斷性變更) 的類別,以及 .NET 小組評估每個類別中的變更的方式。This article outlines the categories of compatibility changes (or breaking changes) and the way in which the .NET team evaluates changes in each of these categories. 瞭解 .NET 小組如何解決可能的重大變更,對於在修改現有 Api 行為的dotnet/runtime GitHub 存放庫中開啟提取要求的開發人員而言特別有用。Understanding how the .NET team approaches possible breaking changes is particularly helpful for developers who open pull requests in the dotnet/runtime GitHub repository that modify the behavior of existing APIs.

注意

如需相容性類別的定義,例如二進位檔案相容性和回溯相容性,請參閱中斷性變更類別For a definition of compatibility categories, such as binary compatibility and backward compatibility, see Breaking change categories.

下列各節說明對 .NET Core Api 所做的變更分類,以及它們對應用程式相容性的影響。The following sections describe the categories of changes made to .NET Core APIs and their impact on application compatibility. 變更允許✔️、不允許的 ❌,或需要判斷和評估先前的行為如何❓的可預測、明顯和一致。Changes are either allowed ✔️, disallowed ❌, or require judgment and an evaluation of how predictable, obvious, and consistent the previous behavior was ❓.

注意

除了作為如何評估 .NET Core 程式庫變更的指南之外,程式庫開發人員也可以使用這些準則來評估其程式庫 (以多個 .NET 實作和版本為目標) 的變更。In addition to serving as a guide to how changes to .NET Core libraries are evaluated, library developers can also use these criteria to evaluate changes to their libraries that target multiple .NET implementations and versions.

公用合約的修改Modifications to the public contract

此類別目錄中的變更會修改類型的公用介面區。Changes in this category modify the public surface area of a type. 此類別中的大多數變更都是不允許的,因為它們違反了回溯相容性 (可讓使用舊版 API 開發的應用程式能夠在更新版本上執行而不必重新編譯的能力)。Most of the changes in this category are disallowed since they violate backwards compatibility (the ability of an application that was developed with a previous version of an API to execute without recompilation on a later version).

類型Types

  • 允許✔️:當基底類型已經實作為介面時,從類型移除介面實✔️ ALLOWED: Removing an interface implementation from a type when the interface is already implemented by a base type

  • 需要判斷:將新的介面執行加入至類型REQUIRES JUDGMENT: Adding a new interface implementation to a type

    這是一個可接受的變更,因為它不會對現有的用戶端產生負面影響。This is an acceptable change because it does not adversely affect existing clients. 對類型的任何變更都必須在此處定義的可接受變更的界限內運作,以使新實作維持可接受。Any changes to the type must work within the boundaries of acceptable changes defined here for the new implementation to remain acceptable. 如果您要加入的介面會直接影響設計工具或序列化程式產生無法在低層級取用之程式碼或資料的能力,請格外小心。Extreme caution is necessary when adding interfaces that directly affect the ability of a designer or serializer to generate code or data that cannot be consumed down-level. 其中一個範例是 ISerializable 介面。An example is the ISerializable interface.

  • 需要判斷:引進新的基類REQUIRES JUDGMENT: Introducing a new base class

    如果類型未引進任何新的抽象成員,或變更現有類型的語義或行為,則可以在兩個現有類型之間引進階層。A type can be introduced into a hierarchy between two existing types if it doesn't introduce any new abstract members or change the semantics or behavior of existing types. 例如,在 .NET Framework 2.0 中,DbConnection 類別成為 SqlConnection 的新基底類別,它先前直接衍生自 ComponentFor example, in .NET Framework 2.0, the DbConnection class became a new base class for SqlConnection, which had previously derived directly from Component.

  • 允許✔️:將類型從一個元件移至另一個✔️ ALLOWED: Moving a type from one assembly to another

    元件必須以指向新元件的 TypeForwardedToAttribute 標記。The old assembly must be marked with the TypeForwardedToAttribute that points to the new assembly.

  • 允許✔️:將結構類型變更為 readonly struct 類型✔️ ALLOWED: Changing a struct type to a readonly struct type

    不允許將 readonly struct 類型變更為 struct 類型。Changing a readonly struct type to a struct type is not allowed.

  • 允許✔️:當沒有可存取(公用或受保護)的函式時,將Sealedabstract關鍵字新增至類型✔️ ALLOWED: Adding the sealed or abstract keyword to a type when there are no accessible (public or protected) constructors

  • 允許✔️:展開類型的可見度✔️ ALLOWED: Expanding the visibility of a type

  • 允許 ❌:變更類型的命名空間或名稱DISALLOWED: Changing the namespace or name of a type

  • 允許 ❌:重新命名或移除公用類型DISALLOWED: Renaming or removing a public type

    這會中斷使用已重新命名或已移除之型別的所有程式碼。This breaks all code that uses the renamed or removed type.

  • 不允許 ❌:變更列舉的基礎類型DISALLOWED: Changing the underlying type of an enumeration

    這是編譯時期和行為的中斷性變更,以及可以使屬性引數無法進行剖析的二進位中斷性變更。This is a compile-time and behavioral breaking change as well as a binary breaking change that can make attribute arguments unparsable.

  • 不允許 ❌:密封先前未密封的類型DISALLOWED: Sealing a type that was previously unsealed

  • 不允許 ❌:將介面新增至介面的基底類型集合DISALLOWED: Adding an interface to the set of base types of an interface

    如果介面實作先前未實作的介面,則實作介面原始版本的所有型別都會中斷。If an interface implements an interface that it previously did not implement, all types that implemented the original version of the interface are broken.

  • 需要判斷:從一組衍生的介面中移除基類或介面的類別REQUIRES JUDGMENT: Removing a class from the set of base classes or an interface from the set of implemented interfaces

    介面移除規則有一個例外:您可以新增衍生自已移除之介面的介面實作。There is one exception to the rule for interface removal: you can add the implementation of an interface that derives from the removed interface. 例如,如果型別或介面現在實作 IDisposable (它會實作 IComponent),則可以移除 IDisposableFor example, you can remove IDisposable if the type or interface now implements IComponent, which implements IDisposable.

  • 允許 ❌:將 readonly struct 型別變更為結構DISALLOWED: Changing a readonly struct type to a struct type

    不過,允許將 struct 類型變更為 readonly struct 類型。The change of a struct type to a readonly struct type is allowed, however.

  • 允許 ❌:將結構型別變更為 ref struct 型別, 反之亦然DISALLOWED: Changing a struct type to a ref struct type, and vice versa

  • 允許 ❌:減少類型的可見度DISALLOWED: Reducing the visibility of a type

    但是,允許增加型別的可見性。However, increasing the visibility of a type is allowed.

成員Members

  • 允許✔️:展開非虛擬成員的可見度✔️ ALLOWED: Expanding the visibility of a member that is not virtual

  • 允許✔️:將抽象成員加入至沒有可存取(公用或受保護)之函式的公用類型,或類型為sealed✔️ ALLOWED: Adding an abstract member to a public type that has no accessible (public or protected) constructors, or the type is sealed

    但是,不允許將抽象成員新增至具有可存取 (公用或受保護) 建構函式且不是 sealed 的型別。However, adding an abstract member to a type that has accessible (public or protected) constructors and is not sealed is not allowed.

  • 允許✔️:當類型沒有可存取(公用或受保護)的函式,或類型已密封時,限制受保護成員的可見度✔️ ALLOWED: Restricting the visibility of a protected member when the type has no accessible (public or protected) constructors, or the type is sealed

  • 允許✔️:將成員移至階層中較高的類別,而不是移除它的類型✔️ ALLOWED: Moving a member into a class higher in the hierarchy than the type from which it was removed

  • 允許✔️:新增或移除覆寫✔️ ALLOWED: Adding or removing an override

    覆寫的引進可能會導致先前的取用者在呼叫base時略過覆寫。Introducing an override might cause previous consumers to skip over the override when calling base.

  • 允許✔️:將函式新增至類別,以及如果類別先前沒有任何的函式,則為無參數的函式✔️ ALLOWED: Adding a constructor to a class, along with a parameterless constructor if the class previously had no constructors

    但是,不允許將建構函式新增至先前沒有建構函式且沒有新增無參數建構函式的類別。However, adding a constructor to a class that previously had no constructors without adding the parameterless constructor is not allowed.

  • 允許✔️:將成員從abstract變更為virtual✔️ ALLOWED: Changing a member from abstract to virtual

  • 允許✔️:從 ref readonly 變更為 ref 傳回值(虛擬方法或介面除外)✔️ ALLOWED: Changing from a ref readonly to a ref return value (except for virtual methods or interfaces)

  • 允許✔️:除非欄位的靜態類型是可變的實數值型別,否則從欄位移除readonly✔️ ALLOWED: Removing readonly from a field, unless the static type of the field is a mutable value type

  • 允許✔️:呼叫先前未定義的新事件✔️ ALLOWED: Calling a new event that wasn't previously defined

  • 需要判斷:將新的實例欄位加入至類型REQUIRES JUDGMENT: Adding a new instance field to a type

    此變更會影響序列化。This change impacts serialization.

  • 允許 ❌:重新命名或移除公用成員或參數DISALLOWED: Renaming or removing a public member or parameter

    這會中斷使用已重新命名或已移除之成員或參數的所有程式碼。This breaks all code that uses the renamed or removed member, or parameter.

    這包括從屬性移除或重新命名 getter 或 setter,以及重新命名或移除列舉成員。This includes removing or renaming a getter or setter from a property, as well as renaming or removing enumeration members.

  • 不允許 ❌:將成員新增至介面DISALLOWED: Adding a member to an interface

  • 允許 ❌:變更公用常數或列舉成員的值DISALLOWED: Changing the value of a public constant or enumeration member

  • 允許 ❌:變更屬性、欄位、參數或傳回值的類型DISALLOWED: Changing the type of a property, field, parameter, or return value

  • 允許的 ❌:新增、移除或變更參數的順序DISALLOWED: Adding, removing, or changing the order of parameters

  • 允許 ❌:從參數新增或移除inoutref關鍵字DISALLOWED: Adding or removing the in, out , or ref keyword from a parameter

  • 允許 ❌:重新具名引數(包括變更其大小寫)DISALLOWED: Renaming a parameter (including changing its case)

    這會視為中斷的原因有二:This is considered breaking for two reasons:

  • 允許 ❌:從 ref 傳回值變更為 ref readonly 傳回值DISALLOWED: Changing from a ref return value to a ref readonly return value

  • 允許 ❌️:從 ref readonly 變更為虛擬方法或介面上的 ref 傳回值❌️ DISALLOWED: Changing from a ref readonly to a ref return value on a virtual method or interface

  • 允許 ❌:從成員新增或移除抽象DISALLOWED: Adding or removing abstract from a member

  • 允許 ❌:從成員移除虛擬關鍵字DISALLOWED: Removing the virtual keyword from a member

    雖然這通常不是一個中斷性變更,因為 C# 編譯器傾向於發出 callvirt 中繼語言 (IL) 指令以呼叫非虛擬方法 (callvirt 會執行 Null 檢查,而正常呼叫不會),由於以下幾個原因,此行為並不是不變的:While this often is not a breaking change because the C# compiler tends to emit callvirt Intermediate Language (IL) instructions to call non-virtual methods (callvirt performs a null check, while a normal call doesn't), this behavior is not invariable for several reasons:

    • C# 不是 .NET 以其為目標的唯一語言。C# is not the only language that .NET targets.

    • 只要目標方法為非虛擬且可能不是 Null 時 (例如透過 callvirt?. null 傳播運算子存取的方法),C# 編譯器就會漸漸地嘗試將 最佳化為正常呼叫。The C# compiler increasingly tries to optimize callvirt to a normal call whenever the target method is non-virtual and is probably not null (such as a method accessed through the ?. null propagation operator).

    使方法成為虛擬表示取用者程式碼通常最後會以非虛擬方式呼叫它。Making a method virtual means that the consumer code would often end up calling it non-virtually.

  • 允許 ❌:將虛擬關鍵字新增至成員DISALLOWED: Adding the virtual keyword to a member

  • 允許 ❌:使虛擬成員成為抽象DISALLOWED: Making a virtual member abstract

    虛擬成員提供了一種方法實作,可以由衍生類別覆寫。A virtual member provides a method implementation that can be overridden by a derived class. 抽象成員不提供任何實作,且必須被覆寫。An abstract member provides no implementation and must be overridden.

  • ❌ 不允許:將抽象成員加入具有可存取(公用或受保護)之函式且未密封的公用類型DISALLOWED: Adding an abstract member to a public type that has accessible (public or protected) constructors and that is not sealed

  • 允許 ❌:從成員新增或移除靜態關鍵字DISALLOWED: Adding or removing the static keyword from a member

  • ❌ 不允許:新增可排除現有多載並定義不同行為的多載DISALLOWED: Adding an overload that precludes an existing overload and defines a different behavior

    這會中斷繫結到先前多載的現有用戶端。This breaks existing clients that were bound to the previous overload. 例如,如果某個類別具有接受 UInt32 的方法的單一版本,則現有的取用者在傳遞 Int32 值時將成功繫結至該多載。For example, if a class has a single version of a method that accepts a UInt32, an existing consumer will successfully bind to that overload when passing a Int32 value. 但是,如果新增接受 Int32 的多載,則在重新編譯或使用晚期繫結時,編譯器現在會繫結至新的多載。However, if you add an overload that accepts an Int32, when recompiling or using late-binding, the compiler now binds to the new overload. 如果產生不同的行為,這是一個中斷性變更。If different behavior results, this is a breaking change.

  • 不允許 ❌:將函式新增至先前沒有任何函式的類別,而不加入無參數的函式DISALLOWED: Adding a constructor to a class that previously had no constructor without adding the parameterless constructor

  • 允許 ❌️:將readonly加入至欄位❌️ DISALLOWED: Adding readonly to a field

  • 允許 ❌:減少成員的可見度DISALLOWED: Reducing the visibility of a member

    這包括減少受保護成員的可見度(當有可存取的(publicprotected)的函式,且該類型密封的。This includes reducing the visibility of a protected member when there are accessible (public or protected) constructors and the type is not sealed. 如果不是這種情況,則允許降低受保護成員的可見性。If this is not the case, reducing the visibility of a protected member is allowed.

    允許增加成員的可見度。Increasing the visibility of a member is allowed.

  • 允許 ❌:變更成員的類型DISALLOWED: Changing the type of a member

    無法修改方法的傳回值,或屬性或欄位的型別。The return value of a method or the type of a property or field cannot be modified. 例如,傳回 Object 之方法的簽章不能變更為傳回 String,反之亦然。For example, the signature of a method that returns an Object cannot be changed to return a String, or vice versa.

  • 不允許 ❌:將欄位新增至先前沒有狀態的結構DISALLOWED: Adding a field to a struct that previously had no state

    只要變數型別是無狀態結構,明確指派規則就允許使用未初始化的變數。Definite assignment rules allow the use of uninitialized variables so long as the variable type is a stateless struct. 如果將結構設定為具狀態,程式碼最後可能會遇到未初始化的資料。If the struct is made stateful, code could end up with uninitialized data. 這可能是一個來源中斷和二進位中斷性變更。This is both potentially a source breaking and a binary breaking change.

  • 不允許的 ❌:引發從未引發的現有事件DISALLOWED: Firing an existing event when it was never fired before

行為變更Behavioral changes

組件Assemblies

  • 允許✔️:當仍然支援相同的平臺時,讓元件可✔️ ALLOWED: Making an assembly portable when the same platforms are still supported

  • 允許 ❌:變更元件的名稱DISALLOWED: Changing the name of an assembly

  • 不允許 ❌:變更元件的公開金鑰DISALLOWED: Changing the public key of an assembly

屬性、欄位、參數與傳回值Properties, fields, parameters, and return values

  • 允許✔️:將屬性、欄位、傳回值或輸出參數的值變更為更衍生的類型✔️ ALLOWED: Changing the value of a property, field, return value, or out parameter to a more derived type

    例如,傳回 Object 型別的方法可以傳回 String 執行個體。For example, a method that returns a type of Object can return a String instance. (但是,無法變更方法簽章。)(However, the method signature cannot change.)

  • 允許✔️:如果成員不是虛擬,則增加屬性或參數的接受值範圍✔️ ALLOWED: Increasing the range of accepted values for a property or parameter if the member is not virtual

    雖然可以傳遞給方法的值範圍或成員所傳回的可以展開,但參數或成員類型不能。While the range of values that can be passed to the method or are returned by the member can expand, the parameter or member type cannot. 例如,雖然傳遞至方法的值可以從 0-124 擴充至 0-255,但參數類型無法從 Byte 變更為 Int32For example, while the values passed to a method can expand from 0-124 to 0-255, the parameter type cannot change from Byte to Int32.

  • 不允許 ❌:如果成員是虛擬的,則增加屬性或參數的接受值範圍DISALLOWED: Increasing the range of accepted values for a property or parameter if the member is virtual

    此變更會中斷現有的覆寫成員,這些成員將無法在擴充的值範圍內正常執行。This change breaks existing overridden members, which will not function correctly for the extended range of values.

  • 允許 ❌:減少屬性或參數的接受值範圍DISALLOWED: Decreasing the range of accepted values for a property or parameter

  • 允許 ❌:增加屬性、欄位、傳回值或輸出參數的傳回值範圍DISALLOWED: Increasing the range of returned values for a property, field, return value, or out parameter

  • 允許 ❌:變更屬性、欄位、方法傳回值或out參數的傳回值DISALLOWED: Changing the returned values for a property, field, method return value, or out parameter

  • 允許 ❌:變更屬性、欄位或參數的預設值DISALLOWED: Changing the default value of a property, field, or parameter

  • 允許 ❌:變更數值傳回值的有效位數DISALLOWED: Changing the precision of a numeric return value

  • 需要判斷:剖析輸入和擲回新例外狀況的變更(即使檔中未指定剖析行為也一樣REQUIRES JUDGMENT: A change in the parsing of input and throwing new exceptions (even if parsing behavior is not specified in the documentation

例外狀況Exceptions

  • 允許✔️:擲回比現有例外狀況更多的衍生例外狀況✔️ ALLOWED: Throwing a more derived exception than an existing exception

    因為新的例外狀況是現有例外狀況的子類別,所以先前的例外狀況處理程式碼會繼續處理例外狀況。Because the new exception is a subclass of an existing exception, previous exception handling code continues to handle the exception. 例如,在 .NET Framework 4 中,文化特性建立和擷取方法已開始擲回 CultureNotFoundException 而不是 ArgumentException (如果找不到文化特性)。For example, in .NET Framework 4, culture creation and retrieval methods began to throw a CultureNotFoundException instead of an ArgumentException if the culture could not be found. 因為 CultureNotFoundException 衍生自 ArgumentException,所以這是一個可接受的變更。Because CultureNotFoundException derives from ArgumentException, this is an acceptable change.

  • 允許✔️:擲回NotSupportedExceptionNotImplementedException、更特定的例外狀況 NullReferenceException✔️ ALLOWED: Throwing a more specific exception than NotSupportedException, NotImplementedException, NullReferenceException

  • 允許✔️:擲回被視為無法復原的例外狀況✔️ ALLOWED: Throwing an exception that is considered unrecoverable

    無法復原的例外狀況不應該攔截,而應該由高層級追補處理常式處理。Unrecoverable exceptions should not be caught but instead should be handled by a high-level catch-all handler. 因此,使用者不應該擁有攔截這些明確例外狀況的程式碼。Therefore, users are not expected to have code that catches these explicit exceptions. 無法復原的例外狀況有:The unrecoverable exceptions are:

  • 允許✔️:在新的程式碼路徑中擲回新的例外狀況✔️ ALLOWED: Throwing a new exception in a new code path

    例外狀況必須只套用至以新的參數值或狀態執行,而且不能由目標為舊版的現有程式碼執行的新程式碼路徑。The exception must apply only to a new code-path that's executed with new parameter values or state and that can't be executed by existing code that targets the previous version.

  • 允許✔️:移除例外狀況以啟用更健全的行為或新案例✔️ ALLOWED: Removing an exception to enable more robust behavior or new scenarios

    例如,之前只處理正值並擲回 DivideArgumentOutOfRangeException 方法可以變更為支援負值和正值,而不擲回例外狀況。For example, a Divide method that previously only handled positive values and threw an ArgumentOutOfRangeException otherwise can be changed to support both negative and positive values without throwing an exception.

  • 允許✔️:變更錯誤訊息的文字✔️ ALLOWED: Changing the text of an error message

    開發人員不應該依賴錯誤訊息的文字,這也會根據使用者的文化特性而變更。Developers should not rely on the text of error messages, which also change based on the user's culture.

  • 不允許 ❌:在上述未列出的任何其他情況下擲回例外狀況DISALLOWED: Throwing an exception in any other case not listed above

  • 不允許 ❌:移除以上未列出的任何其他案例中的例外狀況DISALLOWED: Removing an exception in any other case not listed above

屬性Attributes

  • 允許✔️:變更無法觀察的屬性值✔️ ALLOWED: Changing the value of an attribute that is not observable

  • *不*允許 ❌:變更可觀察的屬性值DISALLOWED: Changing the value of an attribute that is observable

  • 需要判斷:移除屬性REQUIRES JUDGMENT: Removing an attribute

    在大部分情況下,移除屬性 (例如NonSerializedAttribute) 是一個中斷性變更。In most cases, removing an attribute (such as NonSerializedAttribute) is a breaking change.

平台支援Platform support

  • 允許✔️:在先前不支援的平臺上支援作業✔️ ALLOWED: Supporting an operation on a platform that was previously not supported

  • 不允許:不支援或現在需要平臺上先前支援之作業的特定 Service PackDISALLOWED: Not supporting or now requiring a specific service pack for an operation that was previously supported on a platform

內部實作的變更Internal implementation changes

  • 需要判斷:變更內部類型的介面區REQUIRES JUDGMENT: Changing the surface area of an internal type

    通常允許此類變更,儘管它們可能會中斷私人反映。Such changes are generally allowed, although they break private reflection. 在一些熱門的協力廠商程式庫或大量開發人員依賴內部 API 的案例中,可能不允許此類變更。In some cases, where popular third-party libraries or a large number of developers depend on the internal APIs, such changes may not be allowed.

  • 需要判斷:變更成員的內部執行REQUIRES JUDGMENT: Changing the internal implementation of a member

    通常允許這些變更,儘管它們可能會中斷私人反映。These changes are generally allowed, although they break private reflection. 在一些客戶程式碼經常依賴私人反映或變更引進非預期之副作用的情況下,可能不允許這些變更。In some cases, where customer code frequently depends on private reflection or where the change introduces unintended side effects, these changes may not be allowed.

  • 允許✔️:改善作業的效能✔️ ALLOWED: Improving the performance of an operation

    修改作業效能的能力是很重要的,但此類變更可能會中斷仰賴目前作業速度的程式碼。The ability to modify the performance of an operation is essential, but such changes can break code that relies upon the current speed of an operation. 對於仰賴非同步作業時間的程式碼尤其如此。This is particularly true of code that depends on the timing of asynchronous operations. 效能變更應該不會影響其他有問題的 API 行為;否則,變更將會中斷。The performance change should have no effect on other behavior of the API in question; otherwise, the change will be breaking.

  • 允許✔️:間接(而且通常會有負面)變更作業的效能✔️ ALLOWED: Indirectly (and often adversely) changing the performance of an operation

    如果由於某些其他原因而未將相關變更歸類為中斷,則這是可以接受的。If the change in question is not categorized as breaking for some other reason, this is acceptable. 通常,需要採取可能包括額外的作業或新增新功能的動作。Often, actions need to be taken that may include extra operations or that add new functionality. 這幾乎一律會影響效能,但對於使相關 API 如預期般運作至關重要。This will almost always affect performance but may be essential to make the API in question function as expected.

  • 允許 ❌:將同步 API 變更為非同步(反之亦然)DISALLOWED: Changing a synchronous API to asynchronous (and vice versa)

程式碼變更Code changes

  • 允許✔️:將params新增至參數✔️ ALLOWED: Adding params to a parameter

  • 允許 ❌:將結構變更為類別,反之亦然DISALLOWED: Changing a struct to a class and vice versa

  • 允許 ❌:將Checked關鍵字新增至程式碼區塊DISALLOWED: Adding the checked keyword to a code block

    此變更可能會導致先前執行的程式碼擲回 OverflowException 且無法接受。This change may cause code that previously executed to throw an OverflowException and is unacceptable.

  • 允許 ❌:從參數移除paramsDISALLOWED: Removing params from a parameter

  • 允許 ❌:變更引發事件的順序DISALLOWED: Changing the order in which events are fired

    開發人員可以合理地預期事件以相同的順序引發,而開發人員程式碼經常會取決於事件的引發順序。Developers can reasonably expect events to fire in the same order, and developer code frequently depends on the order in which events are fired.

  • 允許 ❌:移除指定動作上引發的事件DISALLOWED: Removing the raising of an event on a given action

  • 不允許 ❌:變更給定事件的呼叫次數DISALLOWED: Changing the number of times given events are called

  • 不允許 ❌:將 FlagsAttribute 新增至列舉類型DISALLOWED: Adding the FlagsAttribute to an enumeration type