【.NET/C#】サポートするプラットフォームを指定する【CA1416】

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【.NET/C#】サポートするプラットフォームを指定する【CA1416】

2024-9-23 | ,

.NETでサポートするプラットフォーム(OS)を指定して規則CA1416に準じたい!

概要

今回の記事では、.NETでサポートするプラットフォーム(OS)を指定して規則CA1416に準ずる手順を掲載する。

.NETでマルチプラットフォームで動くのでライブラリなどを開発できる。コードで特定のプラットフォーム依存の処理を書くと規則CA1416の警告が表示される。

こんな感じ。
これをなんとかしたい!

仕様書

環境

  • .NET 8(.NET 5以上)

手順書

SupportedOSPlatformUnsupportedOSPlatformというアノテーションを使うとそのブロックの処理がサポートする、サポートしないプラットフォームをそれぞれ指定できる。

下記のコードはWindowsのレジストリから設定してるテーマがダークテーマかどうか判定してる。

using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.Versioning;

namespace Test
{
    public static class Theme
    {
        public static bool IsDark()
        {
            const string registryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
            const string valueName = "AppsUseLightTheme";

            try
            {
                using (RegistryKey? key = Registry.CurrentUser.OpenSubKey(registryKeyPath))
                {
                    if (key != null)
                    {
                        object? registryValue = key.GetValue(valueName);
                        if (registryValue is int intValue)
                        {
                            Debug.WriteLine($"intValue: {intValue}");
                            return intValue == 0;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
            }

            return false;
        }
    }
}

レジストリはWindowsの仕組みなのでWindows以外のプラットフォームでは処理できない。処理できないんだけどもこのままではどのプラットフォームからもこのコードを呼ばれる可能性がある。Windows以外のプラットフォームでこのコードが実行されるとおそらく例外かエラーが発生する。

規則CA1416はこんな感じで特定のプラットフォーム依存のコードが想定外のプラットフォームから実行される可能性があるコードに対して発生する。

この警告を消すにはSupportedOSPlatformを使って対応してるプラットフォームを指定する。

using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.Versioning;

namespace Test
{
    public static class Theme
    {
        [SupportedOSPlatform("windows")]
        public static bool IsDark()
        {
            const string registryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
            const string valueName = "AppsUseLightTheme";

            try
            {
                using (RegistryKey? key = Registry.CurrentUser.OpenSubKey(registryKeyPath))
                {
                    if (key != null)
                    {
                        object? registryValue = key.GetValue(valueName);
                        if (registryValue is int intValue)
                        {
                            Debug.WriteLine($"intValue: {intValue}");
                            return intValue == 0;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
            }

            return false;
        }
    }
}

[SupportedOSPlatform("windows")]とそて直下のブロックがwindowsに対応していることを明示することで警告が消える。

windows以外のプラットフォームを指定する例。

[SupportedOSPlatform("linux")]
public static void PutMessageOnlyLinux()
{
    Debug.WriteLine("Linux Only!");
}

プラットフォームとバージョンを指定する例。

[SupportedOSPlatform("ios14.0")]
public static void PutMessageOnlyiOS()
{
    Debug.WriteLine("iOS Only!");
}

逆にサポートしないプレットフォームを指定する例。

[UnsupportedOSPlatform("android")]
public static void PutMessageExceptAndroid()
{
    Debug.WriteLine("Other than Android!");
}

まとめ(感想文)

マルチプラットフォーム開発ではこういう場合分けが必要になってくると思う今日この頃。

引用・参考文献

下記のページを参考にさせていただきました。ありがとうございました。