Freigeben über


Ändern von Regeln für Kompatibilität

In der gesamten Geschichte hat .NET versucht, ein hohes Maß an Kompatibilität von Version zu Version und implementierungsübergreifend von .NET aufrechtzuerhalten. Obwohl .NET 5 (und .NET Core) und höhere Versionen als neue Technologie im Vergleich zu .NET Framework betrachtet werden können, begrenzen zwei Hauptfaktoren die Fähigkeit dieser Implementierung von .NET, von .NET Framework zu unterscheiden:

  • Eine große Anzahl von Entwicklern hat entweder ursprünglich entwickelt oder weiter .NET Framework-Anwendungen entwickelt. Sie erwarten ein konsistentes Verhalten in .NET-Implementierungen.
  • Mit .NET Standard-Bibliotheksprojekten können Entwickler Bibliotheken erstellen, die auf allgemeine APIs abzielen, die von .NET Framework und .NET 5 (und .NET Core) und höheren Versionen gemeinsam verwendet werden. Entwickler erwarten, dass sich eine in einer .NET-Anwendung verwendete Bibliothek identisch mit derselben Bibliothek verhält, die in einer .NET Framework-Anwendung verwendet wird.

Zusammen mit der Kompatibilität über .NET-Implementierungen erwarten Entwickler ein hohes Maß an Kompatibilität in allen Versionen einer bestimmten Implementierung von .NET. Insbesondere sollte code, der für eine frühere Version von .NET Core geschrieben wurde, nahtlos auf .NET 5 oder einer höheren Version ausgeführt werden. Tatsächlich erwarten viele Entwickler, dass die neuen APIs, die in neu veröffentlichten Versionen von .NET gefunden wurden, auch mit den Vorabversionen kompatibel sein sollten, in denen diese APIs eingeführt wurden.

In diesem Artikel werden Änderungen beschrieben, die sich auf Kompatibilität und die Art und Weise auswirken, in der das .NET-Team jeden Änderungstyp auswertet. Das Verständnis, wie das .NET-Team mögliche Änderungen annimmt, ist besonders hilfreich für Entwickler, die Pullanforderungen öffnen, die das Verhalten vorhandener .NET-APIs ändern.

In den folgenden Abschnitten werden die Kategorien von Änderungen beschrieben, die an .NET-APIs vorgenommen wurden, und deren Auswirkungen auf die Anwendungskompatibilität. Änderungen sind entweder zulässig (✔️), nicht zulässig (❌) oder erfordern ein Urteil und eine Bewertung, wie vorhersehbar, offensichtlich und konsistent das vorherige Verhalten war (❓).

Hinweis

  • Neben der Bewertung von Änderungen an .NET-Bibliotheken können Bibliotheksentwickler diese Kriterien auch verwenden, um Änderungen an ihren Bibliotheken zu bewerten, die auf mehrere .NET-Implementierungen und -Versionen abzielen.
  • Informationen zu den Kompatibilitätskategorien, z. B. Vorwärts- und Abwärtskompatibilität, finden Sie unter Wie Codeänderungen die Kompatibilität beeinflussen können.

Änderungen am öffentlichen Vertrag

Änderungen in dieser Kategorie ändern den öffentlichen Oberflächenbereich eines Typs. Die meisten Änderungen in dieser Kategorie sind unzulässig, da sie die Abwärtskompatibilität verletzen (die Fähigkeit einer Anwendung, die mit einer früheren Version einer API entwickelt wurde, ohne erneute Kompilierung für eine spätere Version auszuführen).

Typen

  • ✔️ ALLOWED: Entfernen einer Schnittstellenimplementierung aus einem Typ, wenn die Schnittstelle bereits von einem Basistyp implementiert wird

  • ERFORDERT URTEIL: Hinzufügen einer neuen Schnittstellenimplementierung zu einem Typ

    Dies ist eine akzeptable Änderung, da sie vorhandene Clients nicht beeinträchtigt. Alle Änderungen am Typ müssen innerhalb der Grenzen zulässiger Änderungen funktionieren, die hier definiert sind, damit die neue Implementierung akzeptabel bleibt. Extreme Vorsicht ist erforderlich, wenn Sie Schnittstellen hinzufügen, die sich direkt auf die Fähigkeit eines Designers oder Serialisierers auswirken, Code oder Daten zu generieren, die nicht auf der Unterebene verbraucht werden können. Ein Beispiel ist die ISerializable Schnittstelle.

  • ERFORDERT URTEIL: Einführung einer neuen Basisklasse

    Ein Typ kann in eine Hierarchie zwischen zwei vorhandenen Typen eingeführt werden, wenn keine neuen abstrakten Elemente eingeführt oder die Semantik oder das Verhalten vorhandener Typen geändert werden. In .NET Framework 2.0 wurde die Klasse DbConnection beispielsweise zu einer neuen Basisklasse für SqlConnection, die zuvor direkt von Component abgeleitet war.

  • ✔️ ZULÄSSIG: Verschieben eines Typs von einer Assembly zu einer anderen

    Die alte Baugruppe muss mit der TypeForwardedToAttribute gekennzeichnet werden, die auf die neue Baugruppe hinweist.

  • ✔️ ALLOWED: Ändern eines Strukturtyps in einen readonly struct Typ

    Das Ändern eines readonly struct Typs in einen struct Typ ist nicht zulässig.

  • ✔️ ZULÄSSIG: Hinzufügen des Schlüsselworts sealed oder abstract zu einem Typ, wenn keine zugänglichen (öffentlichen oder geschützten) Konstruktoren vorhanden sind

  • ✔️ ALLOWED: Die Sichtbarkeit eines Typs erweitern

  • NICHT ZULÄSSIG: Ändern des Namespaces oder des Namens eines Typs

  • NICHT ZULÄSSIG: Umbenennen oder Entfernen eines öffentlichen Typs

    Dadurch wird der gesamte Code, der den umbenannten oder entfernten Typ verwendet, unterbrochen.

    Hinweis

    In seltenen Fällen kann .NET eine öffentliche API entfernen. Weitere Informationen finden Sie unter API-Entfernung in .NET. Weitere Informationen zur .NET-Supportrichtlinie finden Sie unter .NET-Supportrichtlinie.

  • NICHT ZULÄSSIG: Ändern des zugrunde liegenden Typs einer Enumeration

    Dies ist ein Breaking Change der Kompilierzeit und des Verhaltens und darüber hinaus ein binärer Breaking Change, durch die die Analyse der Attributargumente unterbunden werden könnte.

  • NICHT ZULÄSSIG: Versiegeln eines bisher nicht versiegelten Typs

  • NICHT ERLAUBT: Eine Schnittstelle zu den Basistypen einer Schnittstelle hinzufügen

    Wenn eine Schnittstelle eine Schnittstelle implementiert, die sie zuvor nicht implementiert hatte, funktionieren alle Typen nicht mehr, die die ursprüngliche Version der Schnittstelle implementiert haben.

  • ERFORDERT URTEIL: Entfernen einer Klasse aus der Gruppe von Basisklassen oder einer Schnittstelle aus dem Satz implementierter Schnittstellen

    Es gibt eine Ausnahme von der Regel zum Entfernen der Schnittstelle: Sie können die Implementierung einer Schnittstelle hinzufügen, die von der entfernten Schnittstelle abgeleitet wird. Sie können beispielsweise IDisposable entfernen, wenn der Typ oder die Schnittstelle jetzt IComponent implementiert, das wiederum IDisposable implementiert.

  • NICHT ZULÄSSIG: Ändern eines readonly struct Typs in einen Strukturtyp

    Die Änderung eines struct Typs in einen readonly struct Typ ist jedoch zulässig.

  • NICHT ZULÄSSIG: Ändern eines Strukturtyps in einen ref struct Typ und umgekehrt

  • NICHT ZULÄSSIG: Verringern der Sichtbarkeit eines Typs

    Das Erhöhen der Sichtbarkeit eines Typs ist jedoch zulässig.

Elemente

  • ✔️ ERLAUBT: Erweiterung der Sichtbarkeit eines Mitglieds, das nicht virtuell ist

  • ✔️ ZULÄSSIG: Hinzufügen eines abstrakten Members zu einem öffentlichen Typ, der keine zugänglichen (öffentlichen oder geschützten) Konstruktoren hat, oder wenn der Typ versiegelt ist

    Das Hinzufügen eines abstrakten Elements zu einem Typ mit zugänglichen (öffentlichen oder geschützten) Konstruktoren und der nicht sealed ist, ist jedoch nicht zulässig.

  • ✔️ ZULÄSSIG: Einschränken der Sichtbarkeit eines geschützten Members, wenn der Typ keine zugänglichen (öffentlichen oder geschützten) Konstruktoren hat, oder wenn der Typ versiegelt ist

  • ✔️ ALLOWED: Verschieben eines Elements in eine Klasse höher in der Hierarchie als der Typ, aus dem es entfernt wurde

  • ✔️ ZULÄSSIG: Hinzufügen oder Entfernen einer Außerkraftsetzung

    Die Einführung einer Außerkraftsetzung kann dazu führen, dass vorherige Consumer beim Aufrufen von base die Außerkraftsetzung überspringen.

  • ✔️ ALLOWED: Hinzufügen eines Konstruktors zu einer Klasse zusammen mit einem parameterlosen Konstruktor, wenn die Klasse zuvor keine Konstruktoren hatte

    Das Hinzufügen eines Konstruktors zu einer Klasse, die zuvor keine Konstruktoren hatte, ohne den parameterlosen Konstruktor hinzuzufügen, ist nicht zulässig.

  • ✔️ ALLOWED: Ändern eines Mitglieds von abstract zu virtual

  • ✔️ ERLAUBT: Wechseln von einem ref readonly zu einem ref Rückgabewert (mit Ausnahme virtueller Methoden oder Schnittstellen)

  • ✔️ ZULÄSSIG: Entfernen von readonly aus einem Feld, es sei denn, der statische Typ des Felds ist ein veränderlicher Werttyp

  • ✔️ ALLOWED: Aufrufen eines neuen Ereignisses, das zuvor nicht definiert wurde

  • ERFORDERT URTEIL: Hinzufügen eines neuen Instanzfelds zu einem Typ

    Diese Änderung wirkt sich auf die Serialisierung aus.

  • NICHT ERLAUBT: Umbenennen oder Entfernen eines öffentlichen Mitglieds oder Parameters

    Dadurch wird der gesamte Code, der das umbenannte oder entfernte Element oder den Parameter verwendet, unterbrochen.

    Dazu gehört auch das Entfernen oder Umbenennen eines Getters oder Setters aus einer Eigenschaft sowie das Umbenennen oder Entfernen von Enumerationsmembern.

  • ERFORDERT URTEIL: Hinzufügen eines Mitglieds zu einer Schnittstelle

    Es handelt sich zwar um eine grundlegende Änderung in dem Sinne, dass Ihre .NET-Mindestversion auf .NET Core 3.0 (C# 8.0) angehoben wird; dies ist der Zeitpunkt, an dem Standardschnittstellenmember (DIMs) eingeführt wurden. Es ist jedoch erlaubt, ein statisches, nicht abstraktes, nicht virtuelles Mitglied zu einer Schnittstelle hinzuzufügen.

    Wenn Sie eine Implementierung bereitstellen, führt das Hinzufügen eines neuen Elements zu einer vorhandenen Schnittstelle nicht unbedingt zu Kompilierungsfehlern in nachgeschalteten Assemblys. Allerdings unterstützen nicht alle Sprachen DIMs. In einigen Szenarien kann die Laufzeit auch nicht entscheiden, welches Standardschnittstellenelement aufgerufen werden soll. In einigen Szenarien werden Schnittstellen nach ref struct Typen implementiert. Da ref struct-Typen nicht geboxt werden können, können sie daher nicht in Schnittstellentypen umgewandelt werden. ref struct Daher müssen Typen eine implizite Implementierung für jedes Schnittstellenelement bereitstellen. Sie können die von der Schnittstelle bereitgestellte Standardimplementierung nicht verwenden. Aus diesen Gründen sollten Sie sorgfältig abwägen, wenn Sie ein Mitglied zu einer vorhandenen Schnittstelle hinzufügen.

  • NICHT ZULÄSSIG: Ändern des Werts einer öffentlichen Konstante oder eines Enumerationselements

  • NICHT ZULÄSSIG: Ändern des Typs einer Eigenschaft, eines Felds, eines Parameters oder eines Rückgabewerts

  • NICHT ZULÄSSIG: Hinzufügen, Entfernen oder Ändern der Reihenfolge von Parametern

  • NICHT ZULÄSSIG: Hinzufügen oder Entfernen des In-, Out- oder Ref-Schlüsselworts aus einem Parameter

  • NICHT ZULÄSSIG: Umbenennen eines Parameters (einschließlich der Änderung seiner Groß-/Kleinschreibung)

    Dies gilt aus zwei Gründen als Bruch:

  • NICHT ZULÄSSIG: Ändern eines ref Rückgabewerts in einen ref readonly Rückgabewert

  • ❌= NICHT ZULÄSSIG: Wechseln von einem ref readonly in einen ref Rückgabewert auf einer virtuellen Methode oder Schnittstelle

  • NICHT ZULÄSSIG: Hinzufügen oder Entfernen von abstract zu oder aus einem Member

  • NICHT ZULÄSSIG: Entfernen des Schlüsselworts virtual aus einem Member

  • NICHT ZULÄSSIG: Hinzufügen des Schlüsselworts virtual zu einem Member

    Dies ist zwar häufig keine grundlegende Änderung, da der C#-Compiler in der Regel Callvirt Intermediate Language (IL)-Anweisungen ausgibt, um nicht virtuelle Methoden aufzurufen (callvirt führt eine NULL-Prüfung durch, während ein normaler Aufruf nicht funktioniert), ist dieses Verhalten aus mehreren Gründen nicht unveränderlich:

    • C# ist nicht die einzige Sprache, auf die .NET ausgerichtet ist.
    • Der C#-Compiler versucht zunehmend, callvirt zu einem normalen Aufruf zu optimieren, wann immer die Zielmethode nicht virtuell ist und wahrscheinlich nicht NULL ist (z. B. eine Methode, auf die über den "?. NULL-Weitergabe-Operator" zugegriffen wird).

    Aus einer Methode eine virtuelle Methode zu machen bedeutet, dass der Consumercode sie oft nicht virtuell aufruft.

  • NICHT ZULÄSSIG: Umwandeln eines virtuellen Members in einen abstrakten Member

    Ein virtuelles Element stellt eine Methodenimplementierung bereit, die von einer abgeleiteten Klasse überschrieben werden kann . Ein abstrakter Member stellt keine Implementierung bereit und muss außer Kraft gesetzt werden.

  • NICHT ZULÄSSIG: Hinzufügen des Schlüsselworts sealed zu einem Schnittstellenmember

    Durch das Hinzufügen sealed zu einem Standardschnittstellenelement wird es nicht virtuell, wodurch verhindert wird, dass die Implementierung dieses Elements vom abgeleiteten Typ aufgerufen wird.

  • NICHT ERLAUBT: Hinzufügen eines abstrakten Mitglieds zu einem öffentlichen Typ mit zugänglichen (öffentlichen oder geschützten) Konstruktoren, der nicht versiegelt ist

  • NICHT ZULÄSSIG: Hinzufügen oder Entfernen des statischen Schlüsselworts aus einem Element

  • NICHT ZULÄSSIG: Hinzufügen einer Überladung, die eine vorhandene Überladung ausschließt und ein anderes Verhalten definiert

    Dies unterbricht vorhandene Clients, die an die vorherige Überladung gebunden waren. Wenn eine Klasse beispielsweise eine einzelne Version einer Methode hat, die UInt32 akzeptiert, wird ein vorhandener Consumer erfolgreich an diese Überladung gebunden, wenn ein Int32-Wert übergeben wird. Wenn Sie jedoch eine Überladung hinzufügen, die ein Int32 akzeptiert, wird der Compiler beim erneuten Kompilieren oder bei der Verwendung einer späten Bindung jetzt an die neue Überladung gebunden. Wenn unterschiedliche Verhaltensergebnisse auftreten, ist dies eine bahnbrechende Änderung.

  • DISALLOWED: Hinzufügen eines Konstruktors zu einer Klasse, die zuvor keinen Konstruktor hatte, ohne den parameterlosen Konstruktor hinzuzufügen

  • ❌️ NICHT ZULÄSSIG: Hinzufügen von readonly (schreibgeschützt) zu einem Feld

  • NICHT ZULÄSSIG: Verringern der Sichtbarkeit eines Members

    Dies schließt die Verringerung der Sichtbarkeit eines geschützten Mitglieds ein, wenn zugängliche (public oder protected) Konstruktoren vorhanden sind und der Typ nichtversiegelt ist. Wenn dies nicht der Fall ist, ist die Verringerung der Sichtbarkeit eines geschützten Elements zulässig.

    Das Erhöhen der Sichtbarkeit eines Mitglieds ist zulässig.

  • NICHT ZULÄSSIG: Ändern des Typs eines Mitglieds

    Der Rückgabewert einer Methode oder des Typs einer Eigenschaft oder eines Felds kann nicht geändert werden. So kann beispielsweise die Signatur einer Methode, die ein Object zurückgibt, nicht geändert werden, um ein String zurückzugeben, oder umgekehrt.

  • DISALLOWED: Hinzufügen eines Instanzfelds zu einer Struktur ohne nicht-öffentliche Felder

    Wenn eine Struktur nur über öffentliche Felder oder keine Felder verfügt, können Aufrufer lokale Variablen dieses Strukturtyps deklarieren, ohne den Konstruktor der Struktur aufzurufen oder die lokale Variable zuerst auf default(T) zu initialisieren, solange alle öffentlichen Felder der Struktur vor der ersten Verwendung festgelegt werden. Das Hinzufügen neuer Felder - öffentlich oder nicht öffentlich - zu einer solchen Struktur stellt eine Änderung am Quellcode für diese Aufrufer dar, da der Compiler jetzt fordert, dass die zusätzlichen Felder initialisiert werden müssen.

    Darüber hinaus ist das Hinzufügen neuer Felder – ob öffentlich oder nicht öffentlich – zu einer Struktur ohne Felder oder nur mit öffentlichen Feldern ein binärer Breaking Change für Aufrufer, die [SkipLocalsInit] auf ihren Code angewendet haben. Da der Compiler diese Felder zur Kompilierungszeit nicht kennt, konnte er IL ausgeben, die die Struktur nicht vollständig initialisiert, was dazu führt, dass die Struktur aus nicht initialisierten Stapeldaten erstellt wird.

    Wenn eine Struktur über beliebige nichtöffentliche Felder verfügt, erzwingt der Compiler bereits die Initialisierung über den Konstruktor oder default(T), und das Hinzufügen neuer Instanzfelder ist keine grundlegende Änderung.

  • NICHT ZULÄSSIG: Auslösen eines vorhandenen Ereignisses, das bisher noch nicht ausgelöst wurde

Verhaltensänderungen

Assemblys

  • ✔️ ZULÄSSIG: Übertragbarmachen einer Assembly, wenn dieselben Plattformen weiterhin unterstützt werden

  • NICHT ZULÄSSIG: Ändern des Namens einer Assembly

  • NICHT ZULÄSSIG: Ändern des öffentlichen Schlüssels einer Assembly

Eigenschaften, Felder, Parameter und Rückgabewerte

  • ✔️ ALLOWED: Ändern des Werts einer Eigenschaft, eines Felds, eines Rückgabewerts oder eines Ausgabeparameters in einen abgeleiteten Typ

    Beispielsweise kann eine Methode, die einen Typ von Object zurückgibt, eine String Instanz zurückgeben. (Die Methodensignatur kann jedoch nicht geändert werden.)

  • ✔️ ALLOWED: Erhöhen des Bereichs akzeptierter Werte für eine Eigenschaft oder einen Parameter, wenn das Element nicht virtuell ist

    Während sich der Wertebereich, der an die Methode übergeben oder vom Mitglied zurückgegeben werden kann, erweitern kann, kann der Parameter- oder Mitgliedstyp nicht. Während die an eine Methode übergebenen Werte z. B. von 0 bis 124 auf 0 bis 255 erhöht werden können, kann der Parametertyp nicht von Byte zu Int32 geändert werden.

  • DISALLOWED: Erhöhen des Zulässigen Wertebereichs für eine Eigenschaft oder einen Parameter, wenn das Element virtuell ist

    Diese Änderung unterbricht bestehende, außer Kraft gesetzte Member, die für den erweiterten Wertebereich dann nicht korrekt funktionieren.

  • NICHT ZULÄSSIG: Verkleinern des Bereichs akzeptierter Werte für eine Eigenschaft oder einen Parameter

  • Nicht zulässig: Erweiterung des Bereichs der zurückgegebenen Werte für eine Eigenschaft, ein Feld, einen Rückgabewert oder Ausgabeparameter

  • DISALLOWED: Ändern der zurückgegebenen Werte für eine Eigenschaft, ein Feld, einen Methodenrückgabewert oder einen Ausgabeparameter

  • NICHT ZULÄSSIG: Ändern des Standardwerts einer Eigenschaft, eines Felds oder eines Parameters

    Das Ändern oder Entfernen eines Parameterstandardwerts ist kein binärer Umbruch. Das Entfernen eines Parameterstandardwerts ist ein Quellumbruch, und das Ändern eines Parameterstandardwerts kann nach der Neukompilierung zu einer Verhaltensunterbrechung führen.

    Aus diesem Grund ist das Entfernen von Parameterstandardwerten im spezifischen Fall des "Verschiebens" dieser Standardwerte in eine neue Methodenüberladung zulässig, um Mehrdeutigkeit zu vermeiden. Ziehen Sie z. B. eine vorhandene Methode MyMethod(int a = 1)in Betracht. Wenn Sie eine Überladung von MyMethod mit zwei optionalen Parametern, a und b, einführen, können Sie die Kompatibilität beibehalten, indem Sie den Standardwert von a auf die neue Überladung übertragen. Nun sind die beiden Überladungen MyMethod(int a) und MyMethod(int a = 1, int b = 2). Dieses Muster ermöglicht MyMethod() das Kompilieren.

  • NICHT ZULÄSSIG: Ändern der Genauigkeit eines numerischen Rückgabewerts

  • ERFORDERT URTEIL: Eine Änderung der Analyse von Eingaben und Auslösen neuer Ausnahmen (auch wenn das Analyseverhalten in der Dokumentation nicht angegeben ist

Ausnahmen

  • ✔️ ZULÄSSIG: Auslösen einer Ausnahme, die stärker abgeleitet ist als eine vorhandene

    Da es sich bei der neuen Ausnahme um eine Unterklasse einer vorhandenen Ausnahme handelt, behandelt der vorherige Ausnahmebehandlungscode weiterhin die Ausnahme. In .NET Framework 4 wurden bei der Kulturerstellung und bei Abrufmethoden eine CultureNotFoundException anstelle einer ArgumentException ausgelöst, wenn die Kultur nicht gefunden werden konnte. Da CultureNotFoundException von ArgumentException abgeleitet wird, ist dies eine akzeptable Änderung.

  • ✔️ ALLOWED: Auslösen einer spezifischeren Ausnahme als NotSupportedException, NotImplementedException, NullReferenceException

  • ✔️ ALLOWED: Auslösen einer Ausnahme, die als nicht wiederherstellbar gilt

    Nicht behebbare Ausnahmen sollten nicht abgefangen werden, sondern von einem übergeordneten Catch-All-Handler behandelt werden. Daher wird nicht erwartet, dass Benutzer Code haben, der diese expliziten Ausnahmen abfangen soll. Nicht behebbare Ausnahmen sind:

  • ✔️ ALLOWED: Auslösen einer neuen Ausnahme in einem neuen Codepfad

    Die Ausnahme darf nur auf einen neuen Codepfad angewendet werden, der mit neuen Parameterwerten oder -zustand ausgeführt wird und nicht von vorhandenem Code ausgeführt werden kann, der auf die vorherige Version ausgerichtet ist.

  • ✔️ ALLOWED: Entfernen einer Ausnahme zum Aktivieren eines robusteren Verhaltens oder neuer Szenarien

    So kann beispielsweise eine Divide-Methode, die bisher nur positive Werte behandelt und andernfalls ein ArgumentOutOfRangeException ausgelöst hat, so geändert werden, dass sowohl negative als auch positive Werte unterstützt werden, ohne eine Ausnahme auszulösen.

  • ✔️ ALLOWED: Ändern des Texts einer Fehlermeldung

    Entwickler sollten sich nicht auf den Text von Fehlermeldungen verlassen, die sich auch auf der Grundlage der Benutzerkultur ändern.

  • NICHT ZULÄSSIG: Auslösen einer Ausnahme in einem anderen Fall, der oben nicht aufgeführt ist

  • NICHT ZULÄSSIG: Entfernen einer Ausnahme in einem anderen Fall, der oben nicht aufgeführt ist

Attribute

  • ✔️ ALLOWED: Ändern des Werts eines Attributs, das nicht feststellbar ist

  • NICHT ZULÄSSIG: Ändern des Werts eines Attributs, das feststellbar ist

  • ERFORDERT URTEIL: Entfernen eines Attributs

    In den meisten Fällen ist das Entfernen eines Attributs (wie z. B. NonSerializedAttribute) eine wesentliche Änderung.

Plattformunterstützung

  • ✔️ ALLOWED: Unterstützen eines Vorgangs auf einer Plattform, die zuvor nicht unterstützt wurde

  • NICHT ZULÄSSIG: Keine Unterstützung von oder das jetzige Anfordern eines bestimmten Service Packs für einen Vorgang, der zuvor auf einer Plattform unterstützt wurde

Interne Implementierungsänderungen

  • ERFORDERT BEURTEILUNG: Ändern der Oberfläche eines internen Typs

    Solche Änderungen sind im Allgemeinen zulässig, obwohl sie private Reflexionen unterbrechen. In einigen Fällen, in denen beliebte Drittanbieterbibliotheken oder eine große Anzahl von Entwicklern von den internen APIs abhängen, sind solche Änderungen möglicherweise nicht zulässig.

  • ERFORDERT ENTSCHEIDUNGSFINDUNG: Änderung der internen Implementierung eines Mitglieds

    Diese Änderungen sind in der Regel zulässig, obwohl sie private Reflexionen unterbrechen. In einigen Fällen, in denen Kundencode häufig von privater Reflexion abhängt oder wenn die Änderung unbeabsichtigte Nebenwirkungen einführt, sind diese Änderungen möglicherweise nicht zulässig.

  • ✔️ ALLOWED: Verbessern der Leistung eines Vorgangs

    Die Möglichkeit, die Leistung eines Vorgangs zu ändern, ist unerlässlich, aber solche Änderungen können Code unterbrechen, der auf der aktuellen Geschwindigkeit eines Vorgangs basiert. Dies gilt insbesondere für Code, der vom Zeitpunkt der asynchronen Vorgänge abhängt. Die Leistungsänderung sollte keine Auswirkungen auf das andere Verhalten der betreffenden API haben; andernfalls wird die Änderung abgebrochen.

  • ✔️ ZULÄSSIG: Indirektes (und häufig negatives) Ändern der Leistung eines Vorgangs

    Wenn die fragliche Änderung aus irgendeinem anderen Grund nicht als Bruch kategorisiert wird, ist dies akzeptabel. Häufig müssen Aktionen ausgeführt werden, die zusätzliche Vorgänge umfassen oder neue Funktionen hinzufügen. Dies wirkt sich fast immer auf die Leistung aus, kann aber wesentlich sein, damit die betreffende API erwartungsgemäß funktioniert.

  • NICHT ZULÄSSIG: Ändern einer synchronen API in eine asynchrone API (und umgekehrt)

Codeänderungen

  • ✔️ ALLOWED: Hinzufügen von Params zu einem Parameter

  • NICHT ERLAUBT: Ändern einer Struktur in eine Klasse und umgekehrt

  • NICHT ZULÄSSIG: Hinzufügen des Schlüsselworts checked zu einem Codeblock

    Diese Änderung kann dazu führen, dass zuvor ausgeführter Code ein OverflowException auslöst und dadurch inakzeptabel wird.

  • NICHT ZULÄSSIG: Entfernen von params aus einem Parameter

  • NICHT ZULÄSSIG: Ändern der Reihenfolge, in der Ereignisse ausgelöst werden

    Entwickler können vernünftigerweise erwarten, dass Ereignisse in derselben Reihenfolge ausgelöst werden, und Der Entwicklercode hängt häufig von der Reihenfolge ab, in der Ereignisse ausgelöst werden.

  • NICHT ZULÄSSIG: Entfernen des Auslösens eines Ereignisses bei einer bestimmten Aktion

  • NICHT ZULÄSSIG: Ändern der Häufigkeit, mit der bestimmte Ereignisse aufgerufen werden

  • NICHT ZULÄSSIG: Hinzufügen des FlagsAttribute zu einem Enumerationstyp

Siehe auch