Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie haben wahrscheinlich das Motto "One .NET" gehört: eine einzige, einheitliche Plattform zum Erstellen eines beliebigen Anwendungstyps. Das .NET SDK enthält ASP.NET Core, Entity Framework Core, Windows Forms, WPF und ML.NET und bietet im Laufe der Zeit Unterstützung für weitere Plattformen. .NET 5+ ist bestrebt, eine Erfahrung bereitzustellen, in der Sie nicht über die verschiedenen Varianten von .NET nachdenken müssen, aber nicht versuchen, das zugrunde liegende Betriebssystem (Os) vollständig abstrahieren zu können. Sie können weiterhin plattformspezifische APIs aufrufen, z. B. P/Invokes und WinRT.
Die Verwendung plattformspezifischer APIs für eine Komponente bedeutet jedoch, dass der Code nicht mehr auf allen Plattformen funktioniert. Wir benötigen eine Möglichkeit, dies zur Entwurfszeit zu erkennen, damit Entwickler Diagnose erhalten, wenn sie versehentlich plattformspezifische APIs verwenden. Um dieses Ziel zu erreichen, hat .NET 5 die Plattformkompatibilitätsanalyse und ergänzende APIs eingeführt, um Entwicklern bei der Identifizierung und Verwendung plattformspezifischer APIs bei Bedarf zu helfen.
Zu den ergänzenden APIs gehören:
- SupportedOSPlatformAttribute um APIs als plattformspezifisch zu kommentieren und UnsupportedOSPlatformAttribute APIs als nicht unterstützt auf einem bestimmten Betriebssystem zu kommentieren. Diese Attribute können optional die Versionsnummer enthalten und wurden bereits auf einige plattformspezifische APIs in den .NET-Kernbibliotheken angewendet.
-
Is<Platform>()
undIs<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)
statische Methoden in der System.OperatingSystem Klasse zum sicheren Aufrufen plattformspezifischer APIs. Beispielsweise kann OperatingSystem.IsWindows() verwendet werden, um einen Aufruf einer Windows-spezifischen API zu schützen, und OperatingSystem.IsWindowsVersionAtLeast() kann verwendet werden, um einen versionierten Windows-API-Aufruf zu schützen. Sehen Sie sich diese Beispiele an, wie diese Methoden als Schutz von plattformspezifischen API-Verweisen verwendet werden können.
Voraussetzungen
Der Plattformkompatibilitätsanalysator ist einer der Roslyn-Codequalitätsanalysatoren. Diese Analyzer sind im .NET SDK enthalten. Die Plattformkompatibilitätsanalyse ist standardmäßig nur für Projekte aktiviert, die auf net5.0
oder eine spätere Version abzielen. Sie können sie jedoch für Projekte aktivieren , die auf andere Frameworks abzielen.
Wie der Analyzer die Plattformabhängigkeit bestimmt
Eine nicht zugeordnete API gilt als funktionieren auf allen Betriebssystemplattformen.
Eine API, die mit
[SupportedOSPlatform("platform")]
gekennzeichnet ist, gilt nur als übertragbar für die angegebene Plattform und alle Plattformen, die Teilmengen davon sind.- Das Attribut kann mehrmals angewendet werden, um mehrere Plattformunterstützung anzugeben, z. B
[SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")]
. . - Wenn die Plattform eine Teilmenge einer anderen Plattform ist, bedeutet das Attribut, dass die Superset-Plattform ebenfalls unterstützt wird. Zum Beispiel impliziert
[SupportedOSPlatform("iOS")]
, dass die API aufiOS
unterstützt wird und auch auf ihrer Superset-Plattform,MacCatalyst
. - Die Analyse erzeugt eine Warnung , wenn plattformspezifische APIs ohne einen geeigneten Plattformkontext referenziert werden:
-
Warnt, wenn das Projekt nicht auf die unterstützte Plattform ausgerichtet ist (z. B. eine Windows-spezifische API, die von einem Projekt für iOS
<TargetFramework>net5.0-ios14.0</TargetFramework>
aufgerufen wird). -
Warnt , wenn das Projekt plattformübergreifend ist und plattformspezifische APIs aufruft (z. B. eine windows-spezifische API, die von plattformübergreifendem TFM
<TargetFramework>net5.0</TargetFramework>
aufgerufen wird). -
Warnt nicht , wenn auf die plattformspezifische API in einem Projekt verwiesen wird, auf das eine der angegebenen Plattformen ausgerichtet ist (z. B. für eine Windows-spezifische API, die von einem Projekt für Fenster
<TargetFramework>net5.0-windows</TargetFramework>
aufgerufen wird und die AssemblyInfo.cs Dateigenerierung für das Projekt aktiviert ist). -
Warnt nicht, wenn der plattformspezifische API-Aufruf durch entsprechende Plattform-Überprüfungsmethoden geschützt wird (z. B. ein Windows-spezifischer API-Aufruf, der durch entsprechende Methoden geschützt ist).
OperatingSystem.IsWindows()
-
Keine Warnung, wenn aus dem gleichen plattformspezifischen Kontext auf die plattformspezifische API verwiesen wird (Aufrufort auch attributiert mit
[SupportedOSPlatform("platform")
)
-
Warnt, wenn das Projekt nicht auf die unterstützte Plattform ausgerichtet ist (z. B. eine Windows-spezifische API, die von einem Projekt für iOS
- Das Attribut kann mehrmals angewendet werden, um mehrere Plattformunterstützung anzugeben, z. B
Eine API, die mit
[UnsupportedOSPlatform("platform")]
gekennzeichnet ist, wird auf der angegebenen Plattform und allen Plattformen, die eine Teilmenge davon sind, als nicht unterstützt betrachtet, ist jedoch für alle anderen Plattformen unterstützt.- Das Attribut kann mehrmals mit verschiedenen Plattformen angewendet werden,
[UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")]
z. B. . - Wenn die Plattform eine Teilmenge einer anderen Plattform ist, bedeutet das Attribut, dass die Superset-Plattform ebenfalls nicht unterstützt wird. Beispielsweise impliziert
[UnsupportedOSPlatform("iOS")]
, dass die API aufiOS
nicht unterstützt wird und auch auf ihrer Superset-Plattform,MacCatalyst
. - Das Analysetool generiert nur dann eine Warnung, wenn
platform
für den gesamten Aufrufort gilt:Warnt, wenn das Projekt auf eine Plattform abzielt, die als nicht unterstützt bezeichnet wird (z. B. wenn die API mit
[UnsupportedOSPlatform("windows")]
versehen ist und die Aufrufstelle<TargetFramework>net5.0-windows</TargetFramework>
anvisiert).Warnt, wenn das Projekt mit mehreren Zielen ausgerichtet ist und die
platform
in der Standardmäßigen MSBuild-Elementgruppe<SupportedPlatform>
enthalten ist oder dieplatform
manuell in derMSBuild
<Gruppe "SupportedPlatform-Elemente> " enthalten ist:<ItemGroup> <SupportedPlatform Include="platform" /> </ItemGroup>
Warnt nicht , wenn Sie eine App erstellen, die nicht auf die nicht unterstützte Plattform ausgerichtet ist oder mehrfach adressiert ist und die Plattform nicht in der standardmäßigen MSBuild-Elementgruppe
<SupportedPlatform>
enthalten ist.
- Das Attribut kann mehrmals mit verschiedenen Plattformen angewendet werden,
Beide Attribute können mit oder ohne Versionsnummern als Teil des Plattformnamens instanziiert werden. Versionsnummern haben das Format
major.minor[.build[.revision]]
.major.minor
ist erforderlich und die Teilebuild
undrevision
sind optional. Beispielsweise gibt "Windows6.1" die Windows-Version 6.1 an, aber "Windows" wird als Windows 0.0 interpretiert.
Weitere Informationen finden Sie in Beispielen dazu, wie die Attribute funktionieren und welche Diagnose sie verursachen.
Wie der Analyzer TFM-Zielplattformen erkennt
Das Analyseprogramm überprüft keine Zielplattformen des Zielframeworkmonikers (TFM) aus MSBuild-Eigenschaften, z. B. <TargetFramework>
oder <TargetFrameworks>
. Wenn die TFM über eine Zielplattform verfügt, fügt MSBuild ein SupportedOSPlatform
Attribut mit dem Zielplattformnamen in die datei AssemblyInfo.cs ein, die vom Analyzer verwendet wird. Wenn das TFM beispielsweise lautet net5.0-windows10.0.19041
, fügt MSBuild das [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")]
Attribut in die datei AssemblyInfo.cs ein, und die gesamte Assembly gilt nur als Windows. Daher würde der Aufruf von reinen Windows-APIs mit Version 7.0 oder niedriger keine Warnungen im Projekt verursachen.
Hinweis
Wenn die Dateigenerierung der AssemblyInfo.cs Datei für das Projekt deaktiviert ist (das heißt, dass die <GenerateAssemblyInfo>
Eigenschaft auf false
festgelegt ist), kann das erforderliche Attribut auf Assembly-Ebene SupportedOSPlatform
nicht von MSBuild hinzugefügt werden. In diesem Fall können Warnungen für eine plattformspezifische API-Nutzung angezeigt werden, auch wenn Sie diese Plattform als Ziel verwenden. Aktivieren Sie die AssemblyInfo.cs-Dateigenerierung, oder fügen Sie das Attribut manuell in Ihrem Projekt hinzu, um die Warnungen zu beheben.
Plattformeinbindung
.NET 6 hat das Konzept der Plattformeinschluss eingeführt, wobei eine Plattform eine Teilmenge einer anderen Plattform sein kann. Ein Attribut für die Teilmengenplattform impliziert die gleiche Unterstützung (oder das Fehlen von Unterstützung) für die übergeordnete Plattform. Wenn eine Plattformüberprüfungsmethode im OperatingSystem Typ über ein SupportedOSPlatformGuard("supersetPlatform")]
Attribut verfügt, supersetPlatform
wird als Obermenge der Betriebssystemplattform betrachtet, auf die die Methode überprüft wird.
Beispielsweise wird die Methode OperatingSystem.IsIOS() zugeschrieben [SupportedOSPlatformGuard("MacCatalyst")]
. Daher gelten die folgenden Aussagen:
- Die OperatingSystem.IsIOS()- und OperatingSystem.IsIOSVersionAtLeast-Methoden überprüfen nicht nur die
iOS
-Plattform, sondern auch dieMacCatalyst
-Plattform. -
[SupportedOSPlatform("iOS")]
impliziert, dass die API aufiOS
und auch auf seiner Superset-Plattform unterstützt wird.MacCatalyst
Sie können das[UnsupportedOSPlatform("MacCatalyst")]
Attribut verwenden, um diese implizite Unterstützung auszuschließen. -
[UnsupportedOSPlatform("iOS")
impliziert, dass die API aufiOS
undMacCatalyst
nicht unterstützt wird. Sie können das[SupportedOSPlatform("MacCatalyst")]
Attribut verwenden, um diesen impliziten Supportmangel auszuschließen.
Betrachten Sie die folgende Abdeckungsmatrix, in der ✔️ angibt, dass die Plattform unterstützt wird, und ❌ anzeigt, dass die Plattform nicht unterstützt wird.
Plattform | SupportedOSPlatform(subset) |
SupportedOSPlatform(superset) |
UnsupportedOSPlatform(subset) |
UnsupportedOSPlatform(superset) |
---|---|---|---|---|
Teilmenge | ✔️ | ❌ | ✔️ | ❌ |
Obermenge | ✔️ | ✔️ | ✔️ | ✔️ |
Tipp
Die gleichen Regeln gelten für die SupportedOSPlatformGuard
und UnsupportedOSPlatformGuard
Attribute.
Der folgende Codeausschnitt zeigt, wie Sie Attribute kombinieren können, um die richtige Unterstützungsebene festzulegen.
// MacCatalyst is a superset of iOS therefore supported on iOS and MacCatalyst
[SupportedOSPlatform("iOS")]
public void ApiOnlySupportedOnIOSAndMacCatalyst() { }
// Does not imply iOS, only supported on MacCatalyst
[SupportedOSPlatform("MacCatalyst")]
public void ApiOnlySupportedOnMacCatalyst() { }
[SupportedOSPlatform("iOS")] // Supported on iOS and MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst support
public void ApiOnlySupportedOnIos() { }
// Unsupported on iOS and MacCatalyst
[UnsupportedOSPlatform("iOS")]
public void ApiUnsupportedOnIOSAndMacCatalyst();
// Does not imply iOS, only unsupported on MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")]
public void ApiUnsupportedOnMacCatalyst() { }
[UnsupportedOSPlatform("iOS")] // Unsupported on iOS and MacCatalyst
[SupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst unsupportedness
public void ApiUnsupportedOnIos() { }
Erweiterte Szenarien für Attributkombinationen
Wenn eine Kombination von
[SupportedOSPlatform]
und[UnsupportedOSPlatform]
Attributen vorhanden ist, werden alle Attribute nach Betriebssystemplattformbezeichner gruppiert:Liste mit ausschließlich unterstützten Plattformen: Wenn die niedrigste Version jeder Betriebssystemplattform das Attribut
[SupportedOSPlatform]
aufweist, gilt die API als nur von den aufgelisteten Plattformen unterstützt und für alle anderen Plattformen als nicht unterstützt. Die optionalen[UnsupportedOSPlatform]
Attribute für jede Plattform können nur eine höhere Version der mindestens unterstützten Version aufweisen, die angibt, dass die API ab der angegebenen Version entfernt wird.// API is only supported on Windows from version 6.2 to 10.0.19041.0 and all versions of Linux // The API is considered not supported for all other platforms. [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] [SupportedOSPlatform("linux")] public void ApiSupportedFromWindows80SupportFromCertainVersion();
Liste mit ausschließlich nicht unterstützten Plattformen: Wenn die niedrigste Version jeder Betriebssystemplattform das Attribut
[UnsupportedOSPlatform]
aufweist, gilt die API als nur von den aufgelisteten Plattformen nicht unterstützt und für alle anderen Plattformen als unterstützt. Die Liste könnte ein Attribut mit derselben Plattform und einer höheren Version[SupportedOSPlatform]
enthalten, was angibt, dass die API ab dieser Version unterstützt wird.// The API is unsupported on all Linux versions was unsupported on Windows until version 10.0.19041.0. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.19041.0")] [UnsupportedOSPlatform("linux")] public void ApiSupportedFromWindows8UnsupportedFromWindows10();
Inkonsistente Liste: Wenn die niedrigste Version für einige Plattformen
[SupportedOSPlatform]
ist, während sie für andere Plattformen[UnsupportedOSPlatform]
ist, wird sie als inkonsistent betrachtet, was für den Analyzer nicht unterstützt wird. Wenn Inkonsistenz auftritt, ignoriert der Analyzer die[UnsupportedOSPlatform]
Plattformen.- Wenn die niedrigsten Versionen der
[SupportedOSPlatform]
- und[UnsupportedOSPlatform]
-Attribute gleich sind, betrachtet der Analyzer die Plattform als Teil der Liste 'Nur für unterstützte Plattformen'.
- Wenn die niedrigsten Versionen der
Plattformattribute können auf Typen, Member (Methoden, Felder, Eigenschaften und Ereignisse) und Assemblys mit unterschiedlichen Plattformnamen oder -versionen angewendet werden.
- Attribute, die auf der Top-Level-Ebene
target
angewendet werden, wirken sich auf alle seine Mitglieder und Typen aus. - Untergeordnete Attribute gelten nur, wenn sie die Regel „Untergeordnete Attribute können die Plattformunterstützung nur einschränken, nicht erweitern“ befolgen.
- Wenn das übergeordnete Element eine Liste mit ausschließlich unterstützten Plattformen aufweist, können die untergeordneten Memberattribute keine neue Plattformunterstützung hinzufügen, da dies die Unterstützung für das übergeordnete Element erweitern würde. Neue Plattformunterstützung kann nur dem übergeordneten Element selbst hinzugefügt werden. Das untergeordnete Element kann jedoch das Attribut
Supported
für dieselbe Plattform mit höheren Versionen aufweisen, da dies die Unterstützung einschränkt. Ebenso kann das untergeordnete Element dasUnsupported
-Attribut mit derselben Plattform aufweisen, da dies die übergeordnete Unterstützung ebenfalls einschränkt. - Wenn das übergeordnete Element eine Liste mit ausschließlich nicht unterstützten Plattformen aufweist, können die untergeordneten Memberattribute Unterstützung für eine neue Plattform hinzufügen, da dies die übergeordnete Unterstützung einschränkt. Es kann jedoch nicht über das
Supported
-Attribut für dieselbe Plattform wie das übergeordnete Element verfügen, da dies die übergeordnete Unterstützung erweitert. Unterstützung für dieselbe Plattform kann dem übergeordneten Element nur in den Fällen hinzugefügt werden, in denen das ursprünglicheUnsupported
-Attribut angewendet wurde.
- Wenn das übergeordnete Element eine Liste mit ausschließlich unterstützten Plattformen aufweist, können die untergeordneten Memberattribute keine neue Plattformunterstützung hinzufügen, da dies die Unterstützung für das übergeordnete Element erweitern würde. Neue Plattformunterstützung kann nur dem übergeordneten Element selbst hinzugefügt werden. Das untergeordnete Element kann jedoch das Attribut
- Wenn
[SupportedOSPlatform("platformVersion")]
mehr als einmal für eine API mit demselbenplatform
Namen angewendet wird, berücksichtigt der Analyzer nur die api mit der Mindestversion. - Wenn
[UnsupportedOSPlatform("platformVersion")]
mehr als zweimal für eine API mit demselbenplatform
Namen angewendet wird, berücksichtigt der Analyzer nur die beiden mit den frühesten Versionen.
Hinweis
Eine API, die zunächst unterstützt wurde, dann aber in einer späteren Version nicht mehr unterstützt (entfernt) wurde, wird voraussichtlich in einer noch späteren Version nicht wieder unterstützt werden.
- Attribute, die auf der Top-Level-Ebene
Beispiele für die Funktionsweise der Attribute und die von ihnen erzeugten Diagnosen
// An API supported only on Windows all versions.
[SupportedOSPlatform("Windows")]
public void WindowsOnlyApi() { }
// an API supported on Windows and Linux.
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
public void SupportedOnWindowsAndLinuxOnly() { }
// an API only supported on Windows 6.2 and later, not supported for all other.
// an API is removed/unsupported from version 10.0.19041.0.
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void ApiSupportedFromWindows8UnsupportedFromWindows10() { }
// an Assembly supported on Windows, the API added from version 10.0.19041.0.
[assembly: SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows10.0.19041.0")]
public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { }
public void Caller()
{
WindowsOnlyApi(); // warns: This call site is reachable on all platforms. 'WindowsOnlyApi()' is only supported on: 'windows'
// This call site is reachable on all platforms. 'SupportedOnWindowsAndLinuxOnly()' is only supported on: 'Windows', 'Linux'
SupportedOnWindowsAndLinuxOnly();
// This call site is reachable on all platforms. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is only supported on: 'windows' from version 6.2 to 10.0.19041.0
ApiSupportedFromWindows8UnsupportedFromWindows10();
// for same platform analyzer only warn for the latest version.
// This call site is reachable on all platforms. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later
AssemblySupportedOnWindowsApiSupportedFromWindows10();
}
// an API not supported on android but supported on all other.
[UnsupportedOSPlatform("android")]
public void DoesNotWorkOnAndroid() { }
// an API was unsupported on Windows until version 6.2.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
public void StartedWindowsSupportFromVersion8() { }
// an API was unsupported on Windows until version 6.2.
// Then the API is removed (unsupported) from version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void StartedWindowsSupportFrom8UnsupportedFrom10() { }
public void Caller2()
{
DoesNotWorkOnAndroid(); // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android'
// This call site is reachable on all platforms. 'StartedWindowsSupportFromVersion8()' is unsupported on: 'windows' 6.2 and before.
StartedWindowsSupportFromVersion8();
// This call site is reachable on all platforms. 'StartedWindowsSupportFrom8UnsupportedFrom10()' is supported on: 'windows' from version 6.2 to 10.0.19041.0
StartedWindowsSupportFrom8UnsupportedFrom10();
}
Gemeldete Warnungen behandeln
Die empfohlene Methode zum Umgang mit dieser Diagnose besteht darin, sicherzustellen, dass Sie nur plattformspezifische APIs aufrufen, wenn sie auf einer geeigneten Plattform ausgeführt werden. Im Folgenden finden Sie die Optionen, mit denen Sie die Warnungen beheben können. wählen Sie aus, welche Für Ihre Situation am besten geeignet ist:
Schützen des Aufrufs: Zu diesem Zweck können Sie den Code bedingt zur Laufzeit aufrufen. Überprüfen Sie, ob Sie auf einer gewünschten Plattform
Platform
laufen, indem Sie eine der Plattform-Check-Methoden verwenden, zum BeispielOperatingSystem.Is<Platform>()
oderOperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)
. Beispiel.Markieren Sie die Aufrufstelle als plattformspezifisch. Sie können sich auch dafür entscheiden, Ihre eigenen APIs als plattformspezifisch zu kennzeichnen und so effektiv nur die Anforderungen an Ihre Anrufer weiterzuleiten. Kennzeichnen Sie die enthaltende Methode, den enthaltenden Typ oder die gesamte Assembly mit denselben Attributen wie den referenzierten plattformabhängigen Aufruf. Beispiele.
Bestätigen des Aufruforts mit einer Plattformüberprüfung: Wenn Sie den Mehraufwand einer zusätzlichen
if
-Anweisung zur Laufzeit vermeiden möchten, verwenden Sie Debug.Assert(Boolean). Beispiel.Löschen Sie den Code. Im Allgemeinen nicht das, was Sie möchten, weil die Genauigkeit verloren geht, wenn Ihr Code von Windows-Benutzern verwendet wird. In Fällen, in denen eine plattformübergreifende Alternative vorhanden ist, ist es wahrscheinlich besser, diese anstelle von plattformspezifischen APIs zu verwenden.
Unterdrücken Sie die Warnung. Sie können die Warnung auch einfach unterdrücken, entweder über einen EditorConfig-Eintrag oder
#pragma warning disable CA1416
. Diese Option sollte jedoch ein letztes Mittel sein, wenn plattformspezifische APIs verwendet werden.Tipp
Wenn Sie Warnungen mithilfe der vorkompilierten
#pragma
-Anweisungen deaktivieren, beachten Sie bei den Bezeichnern, die Sie als Ziel verwenden, die Groß-/Kleinschreibung. Zum Beispiel würdeca1416
die Warnung CA1416 nicht wirklich deaktivieren.
Plattformspezifische APIs durch Schutzmethoden absichern
Der Plattformname der Guard-Methode sollte mit dem namen der aufrufenden plattformabhängigen API-Plattform übereinstimmen. Wenn die Plattformzeichenfolge der aufrufenden API die Version enthält:
muss die Plattformversion (
[SupportedOSPlatform("platformVersion")]
) der Schutzmethode für das Attributversion
größer oder gleich derVersion
der aufrufenden Plattform seinmuss die Plattformversion (
[UnsupportedOSPlatform("platformVersion")]
) der Schutzmethode für das Attributversion
kleiner oder gleich derVersion
der aufrufenden Plattform seinpublic void CallingSupportedOnlyApis() // Allow list calls { if (OperatingSystem.IsWindows()) { WindowsOnlyApi(); // will not warn } if (OperatingSystem.IsLinux()) { SupportedOnWindowsAndLinuxOnly(); // will not warn, within one of the supported context } // Can use &&, || logical operators to guard combined attributes if (OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041))) { ApiSupportedFromWindows8UnsupportedFromWindows10(); } if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041, 0)) { AssemblySupportedOnWindowsApiSupportedFromWindows10(); // Only need to check latest supported version } } public void CallingUnsupportedApis() { if (!OperatingSystem.IsAndroid()) { DoesNotWorkOnAndroid(); // will not warn } if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(6, 2)) { StartedWindowsSupportFromVersion8(); // will not warn } if (!OperatingSystem.IsWindows() || // supported all other platforms (OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041))) { StartedWindowsSupportFrom8UnsupportedFrom10(); // will not warn } }
Wenn Sie Code schützen müssen, der auf Ziele
netstandard
odernetcoreapp
abzielt, bei denen neue OperatingSystem APIs nicht verfügbar sind, kann die RuntimeInformation.IsOSPlatform API verwendet werden und wird vom Analysator respektiert. Es ist jedoch nicht so optimiert wie die neuen APIs, die in OperatingSystem hinzugefügt wurden. Wenn die Plattform in der OSPlatform-Struktur nicht unterstützt wird, können Sie OSPlatform.Create(String) aufrufen und den Plattformnamen übergeben, den der Analyzer ebenfalls berücksichtigt.public void CallingSupportedOnlyApis() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { SupportedOnWindowsAndLinuxOnly(); // will not warn } if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser"))) { ApiOnlySupportedOnBrowser(); // call of browser specific API } }
APIs mit Plattformschutzattributen annotieren und als benutzerdefinierten Schutz verwenden
Wie bereits beschrieben, erkennt das Analysetool die statischen Methoden zum Schutz von Plattformen im Typ OperatingSystem, z. B. OperatingSystem.IsWindows
und RuntimeInformation.IsOSPlatform. Möglicherweise möchten Sie das Guard-Ergebnis jedoch in einem Feld zwischenspeichern und wiederverwenden oder benutzerdefinierte Schutzmethoden zum Überprüfen einer Plattform verwenden. Das Analysetool muss solche APIs als benutzerdefinierten Wächter erkennen und sollte nicht vor auf diese Weise geschützten APIs warnen. Die Guard-Attribute wurden in .NET 6 eingeführt, um dieses Szenario zu unterstützen:
-
SupportedOSPlatformGuardAttribute
kommentiert APIs, die als Schutz für APIs verwendet werden können, die mit SupportedOSPlatformAttributeAnmerkungen versehen sind. -
UnsupportedOSPlatformGuardAttribute
kommentiert APIs, die als Schutz für APIs verwendet werden können, die mit UnsupportedOSPlatformAttributeAnmerkungen versehen sind.
Diese Attribute können optional eine Versionsnummer enthalten. Sie können mehrmals angewendet werden, um mehrere Plattformen zu schützen und zum Kommentieren eines Felds, einer Eigenschaft oder einer Methode zu verwenden.
class Test
{
[UnsupportedOSPlatformGuard("browser")] // The platform guard attribute
#if TARGET_BROWSER
internal bool IsSupported => false;
#else
internal bool IsSupported => true;
#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
{
ApiNotSupportedOnBrowser(); // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'
if (IsSupported)
{
ApiNotSupportedOnBrowser(); // Not warn
}
}
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
{
ApiOnlyWorkOnWindowsLinux(); // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.
if (_isWindowOrLinux)
{
ApiOnlyWorkOnWindowsLinux(); // Not warn
}
}
}
Kennzeichnen der Anrufwebsite als plattformspezifisch
Plattformnamen sollten mit der aufrufenden plattformabhängigen API übereinstimmen. Wenn die Plattformzeichenfolge eine Version enthält:
Für das
[SupportedOSPlatform("platformVersion")]
Attribut sollte die Aufrufplattformversion
größer oder gleich der aufrufenden PlattformVersion
sein.Für das
[UnsupportedOSPlatform("platformVersion")]
-Attribut sollte die Aufruf-Plattformversion
kleiner oder gleich der aufrufenden PlattformVersion
sein.// an API supported only on Windows. [SupportedOSPlatform("windows")] public void WindowsOnlyApi() { } // an API supported on Windows and Linux. [SupportedOSPlatform("Windows")] [SupportedOSPlatform("Linux")] public void SupportedOnWindowsAndLinuxOnly() { } // an API only supported on Windows 6.2 and later, not supported for all other. // an API is removed/unsupported from version 10.0.19041.0. [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] public void ApiSupportedFromWindows8UnsupportedFromWindows10() { } // an Assembly supported on Windows, the API added from version 10.0.19041.0. [assembly: SupportedOSPlatform("Windows")] [SupportedOSPlatform("windows10.0.19041.0")] public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { } [SupportedOSPlatform("windows6.2")] // call site attributed Windows 6.2 or above. public void Caller() { WindowsOnlyApi(); // will not warn as call site is for Windows. // will not warn as call site is for Windows all versions. SupportedOnWindowsAndLinuxOnly(); // will not warn for the [SupportedOSPlatform("windows6.2")] attribute, but warns for [UnsupportedOSPlatform("windows10.0.19041.0")] // This call site is reachable on: 'windows' 6.2 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later. ApiSupportedFromWindows8UnsupportedFromWindows10(); // The call site version is lower than the calling version, so warns: // This call site is reachable on: 'windows' 6.2 and later. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later AssemblySupportedOnWindowsApiSupportedFromWindows10(); } [SupportedOSPlatform("windows10.0.22000")] // call site attributed with windows 10.0.22000 or above. public void Caller2() { // This call site is reachable on: 'windows' 10.0.22000 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later. ApiSupportedFromWindows8UnsupportedFromWindows10(); // will not warn as call site version higher than calling API. AssemblySupportedOnWindowsApiSupportedFromWindows10(); } [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] // call site supports Windows from version 6.2 to 10.0.19041.0. public void Caller3() { // will not warn as caller has exact same attributes. ApiSupportedFromWindows8UnsupportedFromWindows10(); // The call site reachable for the version not supported in the calling API, therefore warns: // This call site is reachable on: 'windows' from version 6.2 to 10.0.19041.0. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later. AssemblySupportedOnWindowsApiSupportedFromWindows10(); } // an API not supported on Android but supported on all other. [UnsupportedOSPlatform("android")] public void DoesNotWorkOnAndroid() { } // an API was unsupported on Windows until version 6.2. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows6.2")] public void StartedWindowsSupportFromVersion8() { } // an API was unsupported on Windows until version 6.2. // Then the API is removed (unsupported) from version 10.0.19041.0. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] public void StartedWindowsSupportFrom8UnsupportedFrom10() { } [UnsupportedOSPlatform("windows")] // Caller no support Windows for any version. public void Caller4() { // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android' DoesNotWorkOnAndroid(); // will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFromVersion8(); // same, will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFrom8UnsupportedFrom10(); } [UnsupportedOSPlatform("windows")] [UnsupportedOSPlatform("android")] // Caller not support Windows and Android for any version. public void Caller4() { DoesNotWorkOnAndroid(); // will not warn as call site not supports Android. // will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFromVersion8(); // same, will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFrom8UnsupportedFrom10(); }
Bestätigen des Aufruforts mit einer Plattformüberprüfung
Alle bedingten Prüfungen, die in den Plattformschutzbeispielen verwendet werden, können auch als Bedingung für Debug.Assert(Boolean) dienen.
// An API supported only on Linux.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
{
Debug.Assert(OperatingSystem.IsLinux());
LinuxOnlyApi(); // will not warn
}