1. ホーム
  2. c#

[解決済み] yield return で全ての列挙体をループさせることなく一度に返す。

2022-04-20 14:48:24

質問

カードのバリデーションエラーを取得するために、以下のような関数を用意しました。 質問は、GetErrorsの処理に関するものです。 どちらのメソッドも同じ戻り値型を持っています。 IEnumerable<ErrorInfo> .

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    var errors = GetMoreErrors(card);
    foreach (var e in errors)
        yield return e;
    
    // further yield returns for more validation errors
}

のエラーをすべて返すことは可能ですか? GetMoreErrors 列挙する必要はないのですか?

どのように解決するのですか?

これは決してバカげた質問ではないし、F#がサポートする yield! コレクション全体に対して yield を1つの項目に対して使用します。(末尾再帰の観点からは非常に便利なのですが...)

残念ながらC#ではサポートされていません。

しかし、複数のメソッドがあり、それぞれが IEnumerable<ErrorInfo> を使用することができます。 Enumerable.Concat を使えば、よりシンプルなコードになります。

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    return GetMoreErrors(card).Concat(GetOtherErrors())
                              .Concat(GetValidationErrors())
                              .Concat(AnyMoreErrors())
                              .Concat(ICantBelieveHowManyErrorsYouHave());
}

しかし、この2つの実装には非常に重要な違いが1つあります。それは、この実装ではすべてのメソッド すぐに しかし、返されたイテレータを一度に1つずつしか使用しません。既存のコードでは、このように GetMoreErrors() を実行する前に が尋ねる。 次のエラーについて

通常、これは重要ではありませんが、いつ何が起こるかを理解しておくことは価値があります。