次の方法で共有


プラットフォーム互換性アナライザー

"One .NET" というモットーを聞いたことがあります。これは、あらゆる種類のアプリケーションを構築するための単一の統合プラットフォームです。 .NET SDK には、ASP.NET Core、Entity Framework Core、Windows フォーム、WPF、および ML.NET が含まれており、時間の経過に伴うより多くのプラットフォームのサポートが追加されます。 .NET 5 以降では、.NET のさまざまな種類について推論する必要はありませんが、基になるオペレーティング システム (OS) を完全に抽象化しようとしないエクスペリエンスを提供するよう努めています。 引き続き、プラットフォーム固有の API (P/Invokes や WinRT など) を呼び出すことができます。

ただし、コンポーネントでプラットフォーム固有の API を使用すると、すべてのプラットフォームでコードが機能しなくなります。 開発者が誤ってプラットフォーム固有の API を使用したときに診断を受け取ることができるように、設計時にこれを検出する方法が必要です。 この目標を達成するために、.NET 5 では プラットフォーム互換性アナライザー と補完的な API が導入され、開発者は必要に応じてプラットフォーム固有の API を識別して使用できます。

補完的な API は次のとおりです。

  • SupportedOSPlatformAttribute API にプラットフォーム固有の注釈を付け、特定の OS でサポートされていない API に注釈を付ける UnsupportedOSPlatformAttribute 。 これらの属性には、必要に応じてバージョン番号を含めることができます。また、コア .NET ライブラリの一部のプラットフォーム固有の API に既に適用されています。
  • Is<Platform>()プラットフォーム固有の API を安全に呼び出すための静的メソッドをSystem.OperatingSystem クラスにIs<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)します。 たとえば、 OperatingSystem.IsWindows() を使用して Windows 固有の API の呼び出しを保護し、 OperatingSystem.IsWindowsVersionAtLeast() を使用してバージョン管理された Windows 固有の API 呼び出しを保護できます。 これらのメソッド プラットフォーム固有の API 参照の保護として使用する方法の例を参照してください。

[前提条件]

プラットフォーム互換性アナライザーは、Roslyn コード品質アナライザーの 1 つです。 これらのアナライザーは 、.NET SDK に含まれています。 プラットフォーム互換性アナライザーは、 net5.0 以降のバージョンを対象とするプロジェクトに対してのみ、既定で有効になっています。 ただし、他のフレームワークを対象とするプロジェクトで 有効に することはできます。

アナライザーがプラットフォームの依存関係を決定する方法

  • 適用の API は、 すべての OS プラットフォームで動作すると見なされます。

  • [SupportedOSPlatform("platform")]でマークされた API は、指定されたプラットフォームとそのサブセットであるプラットフォームにのみ移植可能と見なされます。

    • 属性を複数回適用して、[SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")]など、複数のプラットフォームのサポートを示すことができます。
    • プラットフォームが 別のプラットフォームのサブセットである場合、属性はスーパーセット プラットフォームもサポートされていることを意味します。 たとえば、 [SupportedOSPlatform("iOS")] は、 iOS およびスーパーセット プラットフォーム ( MacCatalyst) でも API がサポートされていることを意味します。
    • プラットフォーム固有の API が適切なプラットフォーム コンテキストなしで参照されている場合、アナライザーは警告を生成します。
      • プロジェクトがサポートされているプラットフォームをターゲットにしていない場合に警告します (たとえば、iOS <TargetFramework>net5.0-ios14.0</TargetFramework>をターゲットとするプロジェクトから呼び出された Windows 固有の API)。
      • プロジェクトがクロスプラットフォームであり、プラットフォーム固有の API (たとえば、クロス プラットフォーム TFM <TargetFramework>net5.0</TargetFramework>から呼び出された Windows 固有の API) を呼び出す場合に警告します。
      • プラットフォーム固有の API が、指定されたプラットフォームのいずれかを対象とするプロジェクト内で参照されている場合は警告しません (たとえば、Windows <TargetFramework>net5.0-windows</TargetFramework> をターゲットとするプロジェクトから呼び出された Windows 固有の API の場合や、プロジェクトに対してAssemblyInfo.csファイルの生成が有効になっている場合など)。
      • プラットフォーム固有の API 呼び出しが対応するプラットフォーム チェック メソッド (たとえば、OperatingSystem.IsWindows()によって保護された Windows 固有の API 呼び出し) によって保護されている場合は警告しません
      • プラットフォーム固有の API が同じプラットフォーム固有のコンテキストから参照されている場合は警告しません (呼び出しサイトも[SupportedOSPlatform("platform")属性付き)。
  • [UnsupportedOSPlatform("platform")]でマークされた API は、指定されたプラットフォームおよびそれがサブセットであるが、他のすべてのプラットフォームでサポートされているプラットフォームではサポートされていないと見なされます。

    • 属性は、 [UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")]など、異なるプラットフォームで複数回適用できます。
    • プラットフォームが 別のプラットフォームのサブセットである場合、属性はスーパーセット プラットフォームもサポートされていないことを意味します。 たとえば、 [UnsupportedOSPlatform("iOS")] は、 iOS およびスーパーセット プラットフォーム ( MacCatalyst) でも API がサポートされていないことを意味します。
    • アナライザーは、呼び出しサイトに対してplatformが有効な場合にのみ警告を生成します。
      • プロジェクトがサポートされていないと属性付けされたプラットフォームをターゲットにしている場合に警告します (たとえば、API が [UnsupportedOSPlatform("windows")] で属性付けされ、呼び出しサイトが<TargetFramework>net5.0-windows</TargetFramework>をターゲットとする場合)。

      • プロジェクトが複数ターゲットで、platformが既定の MSBuild <SupportedPlatform> 項目グループに含まれている場合、またはplatformMSBuild<SupportedPlatform> 項目グループに手動で含まれている場合に警告します。

        <ItemGroup>
            <SupportedPlatform Include="platform" />
        </ItemGroup>
        
      • サポートされていないプラットフォームをターゲットにしていないアプリやマルチターゲットアプリを構築していて、そのプラットフォームが既定の MSBuild <SupportedPlatform>項目グループに含まれていない場合は、警告を表示しません。

  • どちらの属性も、プラットフォーム名の一部としてバージョン番号を含めても、含めなくてもインスタンス化できます。 バージョン番号は major.minor[.build[.revision]]の形式です。 major.minor が必要であり、 buildrevision の部分は省略可能です。 たとえば、"Windows6.1" は Windows バージョン 6.1 を示しますが、"Windows" は Windows 0.0 と解釈されます。

詳細については、 属性の動作と原因となる診断の例を参照してください。

アナライザーが TFM ターゲット プラットフォームを認識する方法

アナライザーは、MSBuild プロパティから <TargetFramework><TargetFrameworks> などのターゲット フレームワーク モニカー (TFM) ターゲット プラットフォームをチェックしません。 TFM にターゲット プラットフォームがある場合、MSBuild はターゲット プラットフォーム名を持つ SupportedOSPlatform 属性を AssemblyInfo.cs ファイルに挿入します。これはアナライザーによって使用されます。 たとえば、TFM が net5.0-windows10.0.19041されている場合、MSBuild によって [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] 属性が AssemblyInfo.cs ファイルに挿入され、アセンブリ全体が Windows のみと見なされます。 そのため、7.0 以下のバージョンの Windows 専用 API が呼び出された場合、プロジェクトでは警告は表示されません。

プロジェクトに対 してAssemblyInfo.cs ファイルの生成が無効になっている場合 (つまり、 <GenerateAssemblyInfo> プロパティが false に設定されている場合)、必要なアセンブリ レベル SupportedOSPlatform 属性を MSBuild で追加することはできません。 この場合、そのプラットフォームをターゲットとしているにもかかわらず、プラットフォーム固有の API の使用に関する警告が表示されることがあります。 この警告は、AssemblyInfo.cs ファイルの生成を有効にするか、自分のプロジェクトに属性を手動で追加することによって解決できます。

プラットフォームの包含

.NET 6 では、1 つのプラットフォームを別のプラットフォームのサブセットにすることができるプラットフォーム インクルージョンの概念が導入されました。 サブセット プラットフォームの注釈は、スーパーセット プラットフォームに対して同じサポート (またはその欠如) を意味します。 OperatingSystem型のプラットフォーム チェック メソッドにSupportedOSPlatformGuard("supersetPlatform")]属性がある場合、supersetPlatformは、メソッドがチェックする OS プラットフォームのスーパーセットと見なされます。

たとえば、 OperatingSystem.IsIOS() メソッドは [SupportedOSPlatformGuard("MacCatalyst")]属性付きです。 したがって、次のステートメントが適用されます。

  • OperatingSystem.IsIOS()メソッドとOperatingSystem.IsIOSVersionAtLeastメソッドは、iOS プラットフォームだけでなく、MacCatalyst プラットフォームもチェックします。
  • [SupportedOSPlatform("iOS")] は、API が iOS およびスーパーセット プラットフォームの MacCatalyst でサポートされていることを意味します。 この暗黙的なサポートを除外するには、 [UnsupportedOSPlatform("MacCatalyst")] 属性を使用できます。
  • [UnsupportedOSPlatform("iOS") は、API が iOS および MacCatalystでサポートされていないことを意味します。 この暗黙的なサポート不足を除外するには、 [SupportedOSPlatform("MacCatalyst")] 属性を使用できます。

次のカバレッジ マトリックスについて考えてみましょう。ここで✔️、プラットフォームがサポートされていることを示し、 ❌ はプラットフォームがサポート されていないこと を示します。

プラットホーム SupportedOSPlatform(subset) SupportedOSPlatform(superset) UnsupportedOSPlatform(subset) UnsupportedOSPlatform(superset)
部分集合 ✔️ ✔️
スーパー ✔️ ✔️ ✔️ ✔️

ヒント

SupportedOSPlatformGuard属性とUnsupportedOSPlatformGuard属性にも同じ規則が適用されます。

次のコード スニペットは、属性を組み合わせて適切なレベルのサポートを設定する方法を示しています。

  // 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() { }

属性の組み合わせの高度なシナリオ

  • [SupportedOSPlatform]属性と[UnsupportedOSPlatform]属性の組み合わせが存在する場合、すべての属性は OS プラットフォーム識別子によってグループ化されます。

    • サポートされている一覧のみ。 各 OS プラットフォームの最小バージョンが [SupportedOSPlatform] 属性である場合、その API はリストに含まれているプラットフォームでのみサポートされ、他のすべてのプラットフォームではサポートされないと見なされます。 各プラットフォームの省略可能な [UnsupportedOSPlatform] 属性は、サポートされている最小バージョンの上位バージョンのみを持つことができます。これは、API が指定されたバージョンから削除されることを示します。

      // 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();
      
    • サポートされていない一覧のみ。 各 OS プラットフォームの最小バージョンが [UnsupportedOSPlatform] 属性である場合、その API はリストに含まれているプラットフォームでのみサポートされず、他のすべてのプラットフォームではサポートされると見なされます。 この一覧には、同じプラットフォームで上位バージョンの [SupportedOSPlatform] 属性を持つことができます。これは、そのバージョンから API がサポートされていることを示します。

      // 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();
      
    • 不整合なリスト。 一部のプラットフォームの最小バージョンが他のプラットフォームで[UnsupportedOSPlatform]されている間に[SupportedOSPlatform]されている場合は、一貫性がないと見なされ、アナライザーではサポートされていません。 不整合が発生した場合、アナライザーは [UnsupportedOSPlatform] プラットフォームを無視します。

      • [SupportedOSPlatform]属性と[UnsupportedOSPlatform]属性の最小バージョンが等しい場合、アナライザーはプラットフォームをサポート対象のみの一覧の一部と見なします。
  • プラットフォーム属性は、異なるプラットフォーム名またはバージョンを持つ型、メンバー (メソッド、フィールド、プロパティ、およびイベント) およびアセンブリに適用できます。

    • 最上位レベルで適用される属性 target 、そのすべてのメンバーと型に影響します。
    • 子レベルの属性は、"子注釈はプラットフォームのサポートを絞り込むことができますが、拡大することはできません" というルールに準拠している場合にのみ適用されます。
      • 親が [サポートのみ] リストを 持っている場合、子メンバー属性は新しいプラットフォーム サポートを追加できません。これは親サポートを拡張するものです。 新しいプラットフォームのサポートは、親自体にのみ追加できます。 ただし、子は、サポートを絞り込むので、新しいバージョンの同じプラットフォームに対して Supported 属性を持つことができます。 また、子は、親のサポートを絞り込むのと同じプラットフォームを持つ Unsupported 属性を持つことができます。
      • 親が サポートされていないリストのみを 持っている場合、子メンバー属性は親のサポートを絞り込むため、新しいプラットフォームのサポートを追加できます。 ただし、親サポートが拡張されるため、親と同じプラットフォームの Supported 属性を持つことはできません。 同じプラットフォームのサポートは、元の Unsupported 属性が適用された親にのみ追加できます。
    • [SupportedOSPlatform("platformVersion")]が同じplatform名の API に複数回適用される場合、アナライザーは最小バージョンの API のみを考慮します。
    • [UnsupportedOSPlatform("platformVersion")]が同じplatform名を持つ API に対して 2 回以上適用される場合、アナライザーは最も古いバージョンの 2 つのみを考慮します。

    最初はサポートされていたが、新しいバージョンではサポートされていない (削除された) API は、それ以降のバージョンでは再サポートされません。

属性のしくみと、属性によって生成される診断の例

// 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();
}

報告された警告を処理する

これらの診断に対処するために推奨される方法は、適切なプラットフォームで実行されている場合にのみプラットフォーム固有の API を呼び出す方法です。 警告に対処するために使用できるオプションを次に示します。状況に最も適した方を選択します。

  • 呼び出しを保護します。 これを実現するには、実行時にコードを条件付きで呼び出します。 OperatingSystem.Is<Platform>()OperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)など、プラットフォーム チェックのいずれかの方法を使用して、目的のPlatformで実行しているかどうかを確認します。

  • 通話サイトをプラットフォーム固有としてマークします。 また、独自の API をプラットフォーム固有としてマークすることもできます。そのため、要件を呼び出し元に効果的に転送するだけです。 参照先のプラットフォーム依存呼び出しと同じ属性を使用して、包含メソッドまたは型、またはアセンブリ全体をマークします。

  • プラットフォーム チェックを使用して呼び出しサイトをアサートします。 実行時に追加の if ステートメントのオーバーヘッドが不要な場合は、 Debug.Assert(Boolean)を使用します。

  • コードを削除します。 一般に、Windows ユーザーがコードを使用すると忠実性が失われることを意味するため、必要なものではありません。 クロスプラットフォームの代替手段が存在する場合は、プラットフォーム固有の API で使用することをお勧めします。

  • 警告を抑制しますEditorConfig エントリまたは#pragma warning disable CA1416を使用して、警告を抑制することもできます。 ただし、このオプションは、プラットフォーム固有の API を使用する場合の最後の手段である必要があります。

    ヒント

    #pragmaプリコンパイラ ディレクティブを使用して警告を無効にすると、対象の識別子では大文字と小文字が区別されます。 たとえば、 ca1416 は実際には警告 CA1416 を無効にしません。

ガード メソッドを使用してプラットフォーム固有の API を保護する

ガード メソッドのプラットフォーム名は、呼び出し元のプラットフォームに依存する API プラットフォーム名と一致する必要があります。 呼び出し元 API のプラットフォーム文字列にバージョンが含まれている場合:

  • [SupportedOSPlatform("platformVersion")]属性の場合、ガード メソッド プラットフォームのversionは、呼び出し元のプラットフォームのVersion以上である必要があります。

  • [UnsupportedOSPlatform("platformVersion")]属性の場合、ガード メソッドのプラットフォーム versionは、呼び出し元のプラットフォームのVersion以下にする必要があります。

    public 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
        }
    }
    
  • 新しいOperatingSystem API を使用できないnetstandardまたはnetcoreappを対象とするコードを保護する必要がある場合は、RuntimeInformation.IsOSPlatform API を使用でき、アナライザーによって尊重されます。 ただし、 OperatingSystemで追加された新しい API ほど最適化されていません。 プラットフォームが OSPlatform 構造体でサポートされていない場合は、 OSPlatform.Create(String) を呼び出してプラットフォーム名を渡すことができます。これはアナライザーも考慮します。

    public void CallingSupportedOnlyApis()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            SupportedOnWindowsAndLinuxOnly(); // will not warn
        }
    
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser")))
        {
            ApiOnlySupportedOnBrowser(); // call of browser specific API
        }
    }
    

プラットフォーム ガード属性を使用して API に注釈を付け、カスタム ガードとして使用する

前に示したように、アナライザーは、OperatingSystem.IsWindowsなどのOperatingSystem型のプラットフォーム ガード静的メソッドとRuntimeInformation.IsOSPlatformを認識します。 ただし、ガードの結果をフィールドにキャッシュして再利用したり、カスタム ガード メソッドを使用してプラットフォームを確認したりできます。 アナライザーは、このような API をカスタム ガードとして認識する必要があり、それらの API によって保護されている API に対して警告を表示しないようにする必要があります。 このシナリオをサポートするために、.NET 6 でガード属性が導入されました。

  • SupportedOSPlatformGuardAttribute は、 SupportedOSPlatformAttributeで注釈付けされた API のガードとして使用できる API に注釈を付けます。
  • UnsupportedOSPlatformGuardAttribute は、 UnsupportedOSPlatformAttributeで注釈付けされた API のガードとして使用できる API に注釈を付けます。

これらの属性には、必要に応じてバージョン番号を含めることができます。 複数のプラットフォームを保護するために複数回適用でき、フィールド、プロパティ、またはメソッドに注釈を付けるために使用できます。

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
        }
    }
}

通話サイトをプラットフォーム固有としてマークする

プラットフォーム名は、呼び出し元のプラットフォーム依存 API と一致する必要があります。 プラットフォーム文字列にバージョンが含まれている場合:

  • [SupportedOSPlatform("platformVersion")]属性の場合、呼び出しサイト プラットフォームのversionは、呼び出し元のプラットフォームの以上である必要があります。Version

  • [UnsupportedOSPlatform("platformVersion")]属性の場合、呼び出しサイト プラットフォームのversionは、呼び出し元のプラットフォームのプラットフォーム以下である必要があります。Version

    // 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();
    }
    

プラットフォーム チェックを使用して呼び出しサイトをアサートする

プラットフォーム ガードの例で使用されるすべての条件付きチェックは、Debug.Assert(Boolean)の条件としても使用できます。

// An API supported only on Linux.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }

public void Caller()
{
    Debug.Assert(OperatingSystem.IsLinux());

    LinuxOnlyApi(); // will not warn
}

こちらも参照ください