17

コードを簡潔にするために、次のことができるようにしたいと思います。コレクションを持って、ラムダ式に一致する最初の要素を見つけます。存在する場合は、プロパティまたは関数の値を返します。存在しない場合は、nullを返します。

更新された例w。クラス

もののコレクションを持っていきましょう

class Stuff
{
    public int Id { get; set; }
    public string Value { get; set; }
    public DateTime? ExecutionTime { get; set; }
}

私が目指しているのは、これを呼んだときにうまく戻る方法です

var list = new Stuff[] { new Stuff() { Id = 1, Value = "label", ExecutionTime = DateTime.Now } };

// would return the value of ExecutionTime for the element in the list
var ExistingTime = list.FirstOrDefault(s => s.Value.Contains("ab")).ExecutionTime;

// would return null
var NotExistingTime = list.FirstOrDefault(s => s.Value.Contains("zzz")).ExecutionTime; 

いくつかのlinq-syntax-fuで可能ですか、それとも先に進む前に戻り値を明示的にチェックする必要がありますか?

元の例w。文字列

var stuff = {"I", "am", "many", "strings", "obviously"};

// would return "OBVIOUSLY"
var UpperValueOfAString = stuff.FirstOrDefault(s => s.contains("bvi")).ToUpper();

// would return null
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.contains("unknown token")).ToUpper();

コメント:ToUpperメソッドと文字列クラスを中心にして質問をわずかに歪めるため、元の例では文字列を使用するべきではありませんでした。更新された例を検討してください

4

3 に答える 3

32

なぜそうしないのですか:

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .FirstOrDefault()

「デフォルト以外のデフォルト」がある場合は、次のことができます。

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .DefaultIfEmpty("Something Else")
     .First()
于 2012-06-27T09:18:55.720 に答える
9

拡張メソッドとしてこれが好きです:

public static U SelectMaybe<T, U>(this T input, Func<T,U> func)
{
    if (input != null) return func(input);
    else return default(U);
}

そして使用法:

var UpperValueOfAString = stuff.FirstOrDefault(s => s.Contains("bvi")).SelectMaybe(x => x.ToUpper());
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.Contains("unknown token")).SelectMaybe(x => x.ToUpper());

これは、デフォルト値をチェーンで返すか (nullこの場合は、その型では正しい)、または関連する関数を呼び出してそれを返します。

于 2012-06-27T09:17:56.550 に答える
4

アップデート:

質問の明確化に基づいて、目的を達成するために追加のコードは必要ありません。where 句と select 射影句を使用するだけです。

var theString = stuff
    .Where(s => s.contains("unknown token"))
    .Select(s => s.ToUpper())
    .FirstOrDefault();


古い回答

コメントで提案されているように (そして別の回答で一般化ToUpperされています)、呼び出しを拡張メソッドでラップします。拡張メソッドは、静的メソッド呼び出しの周りの構文シュガーに要約されるため、null を問題なく処理できます。

static class StringExtensions
{
    public static string PossiblyToUpper(this string s)
    {
        if (s != null)
            return s.ToUpper();

        return null;
    }
}

あなたの呼び出しは次のようになります。

var upperValueOfAStringWannabe = stuff
    .FirstOrDefault(s => s.contains("unknown token"))
    .PossiblyToUpper();

単純に 1 行のスタイル コードをサポートする拡張メソッドが、複数行のコードよりも表現力に優れているかどうかについての議論に過ぎません。結局のところ、コードの意図を表現することは、コードがどのように見えるかよりも重要です。

個人的には、null を処理する拡張メソッドは、通常のメソッドのように甘やかされているため、一見するとわかりにくいと思います。

于 2012-06-27T09:05:42.820 に答える