c# - 辞書からnull可能値を削除し、型を再キャストする

原文 c# .net

次の列挙型があるとします。

public enum CompassDirection
{
    North,
    East,
    South,
    West
}


Dictionary<string, CompassDirection?>:

var dictionary = new Dictionary<string, CompassDirection?>
{
    { "Foo", CompassDirection.North },
    { "Bar", null },
    { "Baz", CompassDirection.West }
};


辞書からnull値をエレガントに削除したり、新しい辞書にコピーしたりして、Dictionary<string, CompassDirection>を取得するにはどうすればよいですか(TValueの汎用引数はnullにできないようになりました)。

私が考えることができる1つの解決策は:

 public static IDictionary<string, CompassDirection> CopyToNonNullableDictionary
    (IDictionary<string, CompassDirection?> input)
 {
     return (from kvp in input
             where kvp.Value != null
             select kvp).ToDictionary(kvp => kvp.Key, kvp => (CompassDirection)kvp.Value);
 }


コピーせずに良い方法はありますか?
答え
IMO、「エレガントにnullを削除する」と言うと、非常に意見の高い回答の領域にいます。

エレガントであることがわかった場合に使用できる2つの方法(1つはLinqと1つはLinq以外)です。 null可能型には、nullかどうかを判別するHasValueプロパティがあります。タイプHasValueプロパティがtrueの場合、Valueプロパティに参照できるため、CompassDirectionにキャストする必要はありません。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main(string[] args)
    {
        var dictionary = new Dictionary<string, CompassDirection?>
        {
            { "Foo", CompassDirection.North },
            { "Bar", null },
            { "Baz", CompassDirection.West }
        };

        Console.WriteLine("New Dictionary 1:");
        PrintDictionary(RemoveNullMethod1(dictionary));

        Console.WriteLine("New Dictionary 2:");     
        PrintDictionary(RemoveNullMethod2(dictionary));
    }

    public static Dictionary<string, CompassDirection> RemoveNullMethod1(Dictionary<string, CompassDirection?> input)
    {
        return input
            .Where(entry => entry.Value.HasValue)
            .ToDictionary(e => e.Key, e => e.Value.Value);
    }

    public static Dictionary<string, CompassDirection> RemoveNullMethod2(Dictionary<string, CompassDirection?> input)
    {
        Dictionary<string, CompassDirection> newDictionary = new Dictionary<string, CompassDirection>();
        foreach(KeyValuePair<string, CompassDirection?> entry in input)
        {
            if (entry.Value.HasValue)
            {
                newDictionary.Add(entry.Key, entry.Value.Value);
            }
        }
        return newDictionary;
    }

    public static void PrintDictionary(Dictionary<string, CompassDirection> input)
    {
        foreach(KeyValuePair<string, CompassDirection> entry in input)
        {
            Console.WriteLine("Key: {0} Value: {1}", entry.Key, entry.Value);
        }
        Console.WriteLine();
    }
}

public enum CompassDirection
{
    North, East, South, West
}


結果:

New Dictionary 1:
Key: Foo Value: North
Key: Baz Value: West

New Dictionary 2:
Key: Foo Value: North
Key: Baz Value: West


Fiddle Demo
関連記事

c# - C++からC#への複雑な構造体のマーシャリング

c# - C#:テキストファイルへの変数の挿入

c# - エンティティフレームワークで作成されたデータベースからヘルパーのドロップダウンリストにアイテムをロードする

c# - Web APIのリクエストに一致する複数のアクションが見つかりました

c# - 日付ピッカーのドロップダウンリストから日付を無効にする

c# - TFSがビルドのgit reposを複製しているときのAppDomainUnloadedException

c# - SQL例外をスローするASP.Netフォーム

c# - 負の角度でも正の値を返すPIDコントローラー

c# - ルールアセンブリを読み込めません

c# - 画像ボタンに画像を読み込む