1. ホーム
  2. c#

[解決済み] C#では、なぜ無名メソッドはyieldステートメントを含むことができないのですか?

2023-03-21 09:14:53

質問

このようなことができたらいいなと思いました(ラムダがyield returnをする)。

public IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new()
{
    IList<T> list = GetList<T>();
    var fun = expression.Compile();

    var items = () => {
        foreach (var item in list)
            if (fun.Invoke(item))
                yield return item; // This is not allowed by C#
    }

    return items.ToList();
}

しかし、匿名メソッドでyieldが使えないことがわかりました。 なぜかというと その yield ドキュメント には、それが許されないと書いてあるだけです。

許されないので、私はただListを作成し、そこにアイテムを追加しました。

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

Eric Lippert は最近、なぜ yield が許されない場合があるのかについて、一連のブログ記事を書きました。

EDIT2です。

  • パート 7 (これは後に投稿されたもので、特にこの質問を扱っています)

おそらくそこで答えが見つかるでしょう...


EDIT1: これは第5部のコメントで、Abhijeet Patelのコメントに対するEricの答えで説明されています。

Q :

エリック

また、以下の点についても教えてください。 なぜ、quot;yields" が 匿名メソッドまたはラムダ式

A :

<ブロッククオート

いい質問ですね。私は 匿名イテレータブロックが欲しいです。そうすれば を作ることができるのは本当に素晴らしいことです。 小さなシーケンスジェネレータを ローカル変数をクローズする小さなシーケンスジェネレータをインプレースで 変数を閉じるような小さなシーケンスジェネレータをインプレースで作ることができたら、本当に素晴らしいことです。なぜそうしないかというと、理由は簡単です。 その理由は簡単で、メリットがコストを上回らないからです。 コストに見合わないからです。シーケンスジェネレータをインプレースにすることのすばらしさは インプレースでシーケンスジェネレータを作ることのすばらしさは をインプレースで作ることのすばらしさは、全体から見れば非常に小さいものです。 をインプレースで作ることの素晴らしさは、全体から見れば非常に小さなものであり、ノミナルメソッド で十分なのです。 で十分です。ですから、そのメリットは ということです。

コストが大きい イテレータ の書き換えは、コンパイラの中で最も複雑な であり 匿名メソッドの書き換えは 2番目に複雑である。匿名 メソッドの中に他の匿名 匿名メソッドは他の匿名メソッドの中に入ることができ、匿名メソッドはイテレータブロックの中に入ることができます。 イテレータブロックの中に入ることができる。そこで というわけで、まず、すべての 無名メソッドを メソッドに書き換えます。これは これはコンパイラがメソッドのILを生成する前に メソッドのILを生成する前にコンパイラが行う最後の2番目の作業です。 このステップが完了すると、イテレータ リライターは イテレータのリライタは、イテレータブロックに無名メソッドがないと見なすことができます。 ブロックには無名メソッドはないと考えることができます。 すでにすべて書き直されています。そのため、イテレータ のリライターは、イテレータを書き換えることだけに集中できます。 イテレータの書き換えに集中できます。 イテレータの書き換えに集中できます。 その中に未実現の匿名メソッドがあるかもしれないことを気にすることなく、イテレータの書き換えに集中できます。

また、イテレータブロックは決して "nest"することはありません。 無名メソッドとは異なります。イテレータ リライターは、すべてのイテレータ ブロックはトップレベルであると考えることができます。

匿名メソッドがイテレータブロックを含むことを許可されている場合 イテレータブロックを含むことができるのであれば これらの仮定は窓の外に出てしまいます。 イテレータブロックに は匿名メソッドを含んでいて を含む無名メソッド イテレータブロックを含み、そのイテレータブロックが を含むイテレータブロックがある... うっそー ここで、ネストしたイテレータを扱えるように をネストしたイテレータブロックやネストした匿名メソッドを扱えるような書き換えパスを書かなければなりません。 ブロックとネストした無名メソッドを同時に扱えるような を同時に扱えるような書き換えパスを書く必要があります。 複雑なアルゴリズムをひとつに統合して より複雑なアルゴリズムに統合することになります。これは 設計も、実装も、テストも、本当に大変です。 設計、実装、テストが大変です。私たちは十分賢いので そう確信しています。私たちは賢いチームです しかし しかし、私たちは でも、「あったらいいな」程度の機能のために、大きな負担を負いたくない。 でも、必要な機能ではありません。-- エリック