質問
C#で独自の遅延実行メカニズムを実装するにはどうすればよいですか
たとえば、次のようになります:
string x = DoFoo();
Do <!> quot; use <!> quot;までDoFooが実行されないように、いくつかの魔法を実行することは可能ですか? x?
解決
ラムダ/デリゲートを使用できます:
Func<string> doit = () => DoFoo();
// - or -
Func<string> doit = DoFoo;
後でdoit
をメソッドのように呼び出すことができます:
string x = doit();
最も近いものは次のようなものだと思います:
Lazy<string> x = DoFoo;
string y = x; // "use" x
これに似たLazy<T>
の定義(未テスト):
public class Lazy<T>
{
private readonly Func<T> func;
private bool hasValue;
private T value;
public Lazy(Func<T> func)
{
this.func = func;
this.hasValue = false;
}
public static implicit operator Lazy<T>(Func<T> func)
{
return new Lazy<T>(func);
}
public static implicit operator T(Lazy<T> lazy)
{
if (!lazy.hasValue)
{
lazy.value = lazy.func();
lazy.hasValue = true;
}
return lazy.value;
}
}
残念ながら、コンパイラの型推論アルゴリズムはFunc<T>
の型を自動推論できないため、暗黙の変換演算子と一致させることはできないようです。デリゲートの型を明示的に宣言する必要があります。これにより、割り当てステートメントがより冗長になります。
// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };
// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);
他のヒント
1つのオプションは、以前は並列拡張ライブラリの。= Frameworkの一部であったLazy<T>
クラスを使用することです。
スレッドを意識した方法でプロセスデータを遅延させることができます。
多少汚いですが、常にyieldキーワードを使用できます:
public IEnumerable<int> DoFoo() {
Console.WriteLine("doing foo");
yield return 10;
}
[Test]
public void TestMethod()
{
var x = DoFoo();
Console.WriteLine("foo aquired?");
Console.WriteLine(x.First());
}
文字列 x を渡す代わりに、文字列を取得するデリゲートを渡します
Func<String> fooFunc=()=>DoFoo();
実行するまで「DoFoo()」を呼び出さないのはなぜですか?
-編集
つまり、<!> quot; use <!> quot;
たとえば、「。ToString()」が呼び出されたときに呼び出されるようにしたい場合は、いつでもクラスを継承し、そこに関数を実装できます(ただし、これは非常に直感的ではありません)。
動作中のLINQをほぼ説明します。 linqクエリはデータの取得方法を記述しますが、データはクエリが反復されるときにのみ取得されます(DoFuncが呼び出されます)。 IQueryable<string>
を受け入れるように設計を変更できるかどうかを検討してください。 a> string
が必要な場所。