22

JavaScriptでは、自己呼び出し関数が表示されることは珍しくありません。

var i = (function(x) {
    return x;
})(42);

// i == 42

私は確かに言語を比較していませんが、サポート付きの言語バージョンを提供すれば、そのような構成はC#に翻訳可能であると考えました。

var i = (delegate(int x) {
    return x;
})(42);

または:

var i = ((x) => {
    return x;
})(42);

あるいは:

var i = (x => x)(42);

ただし、すべてのバージョンにエラーがあります。

メソッド名が必要です

自己呼び出しの匿名メソッドはサポートされていませんか(明示的な禁止、または型推論の不可能性のため)、または私の試みにエラーがありますか?

型を推測できるメソッド宣言(Func<T,T>)がなかったため、暗黙の型、宣言されたメソッドを名前で呼び出すことを意図した図を分類できず、構文を実際に間違えたと推測しています。 。


エラッタ

この質問が殺到する前に:

var i = new Func<int, int>(x => x)(42);

私は型推論を活用したいと思っていたと言うべきですが、過度に暗黙的であるため、それは不可能かもしれないと思います。

それで、質問を少し明確にします。できることはわかってvar i = new Func<int, int>(x => x)(42);いますが、のインスタンスを作成したり、キャストしたりしなくてもFunc、これは可能ですか?

使用事例

好奇心旺盛な(または懸念している)人にとって、ユースケースは次のようなものでした。

var o = new {
    PropertyA = () => {
        // value computation
    }(),
    PropertyB = () => {
        // value computation
    }(),
};
4

2 に答える 2

20
var x = ((Func<int, int>)(y => y * 2))(10);

問題は、コンパイラがそれをデフォルトではなくy => y * 2として分類することを確認した場合、それがである必要があることを通知するコンテキスト情報がない限りです。それをキャストすることで、必要なコンテキストを提供します。ExpressionFuncFuncFunc

于 2013-03-07T18:33:21.863 に答える
11

C#チームの誰かがもっと良い答えを出すことができると思いますが、私は自分のショットを試してみます。ここでの質問は、それがベストプラクティスであるかどうかではなく、可能であるかどうか、そうでない場合はその理由です。

あなたが書くものから始めましょう:

var i = (x => x)(42);

非常に簡単です。整数(42)をラムダに渡すと、ラムダで再生され、同じ値が返されます。そのパラメーターは整数(その使用法から推測される)であり、整数(式から推測される)を返し、i別の整数(戻り値から推測される)です。

残念ながら、これは最初のステップで壊れています。大きなジョンを引用させてください:

コンパイラーは、使用されているコンテキストに基づいて、ラムダ式のパラメーターのタイプを計算しようとします。

どういう意味ですか?実際、コンパイラにはいくつかの情報が必要ですが、使用できるのは次の場合のみです。

  • (Func<int, int>)(x => x))inまたは。のような明示的なキャスト、コンストラクター、または宣言new Func<int, int>(x => x)。ここで必要なタイプは、必要な最終タイプを使用して与えられるか、推測されます。
  • 次のような割り当て(これも最終的なタイプを推測できるため)。Func<int, int> f = (x => x);

あなたの場合、コンパイラはそのパラメータから関数型を推測する必要がありますが、パラメータは式に対して検証され、その逆ではないため、それは不可能です。

なぜこれがC#では不可能なのですか?は単なるデリゲートであるため(x => x)、整数パラメーターを受け入れ(コンパイラーがrhsからlhsを推測し、lhsに従ってrhsを検証できると仮定した場合)、別の整数を返す任意のデリゲートにすることができます。実際には、デリゲート間の変換はC#で許可されていないため、式は無効です(この特別なデリゲートがどの変数にも割り当てられず、将来使用されない場合でも)。Func<int, int>またはExpression<Func<int, int>>または他のデリゲートである可能性があります(パラメーターのbool場合は、蜂でさえある可能性がありますPredicate<bool>)。

もちろん、これはC#の設計上の決定であり、VB.NETの同じ式(たとえば)は完全に有効です。

 Dim i = (Function(x) x)(42)

異なる言語、従うべき異なるルール、C#の目標は、この種のあいまいさを回避することです。

于 2013-03-08T08:48:59.443 に答える