匿名メソッドで値を返す方法は?


89

これは失敗します

string temp = () => {return "test";};

エラーで

デリゲート型ではないため、ラムダ式を型 'string'に変換できません

エラーは何を意味し、どうすれば解決できますか?


明らかにそれとは関係がないのに、「ボイドを返すデリゲートに変換された無名関数は値を返すことができない」というエラーを検索したときに、この質問がGoogleで最初に表示されるのはなぜですか?
カルマリウス2018

回答:


136

ここでの問題は、を返す匿名メソッドを定義したstringが、それをに直接割り当てようとしていることstringです。これは、呼び出されたときにstring直接ではない式を生成しstringます。互換性のあるデリゲートタイプに割り当てる必要があります。この場合、最も簡単な選択はFunc<string>

Func<string> temp = () => {return "test";};

これは、少しキャストするか、デリゲートコンストラクターを使用してラムダのタイプを確立し、その後に呼び出しを行うことで、1行で実行できます。

string temp = ((Func<string>)(() => { return "test"; }))();
string temp = new Func<string>(() => { return "test"; })();

注:両方のサンプルは、 { return ... }

Func<string> temp = () => "test";
string temp = ((Func<string>)(() => "test"))();
string temp = new Func<string>(() => "test")();

ありがとう。では、1行ですべてを行う方法はありません(文字列の割り当てを含む)?必要な値(「テスト」、実際には実際の変数)は別のラムダ内にあるため、上記のように定義しようとするとスコープが失われます。
4thSpace 2012年

@ 4thSpaceそれは、いくつかの邪悪なキャストで1行で行うことができます。私は道を示すために私の答えを更新しました
JaredPar 2012年

または、この場合は、Func<string> temp = () => "test";
Gabe 2012年

または、編集の場合string temp = new Func<string>(() => "test")();
Gabe 2012年

完璧!intを渡したい場合、それを1行で表示できますか?私はこれを試しましたが、うまくいきませんでした:((Func <int、string>)((4)=> {return "test";}))();
4thSpace 2012年

15

関数デリゲートを文字列型に割り当てようとしています。これを試して:

Func<string> temp = () => {return "test";};

これで、次のように関数を実行できます。

string s = temp();

「s」変数の値は「test」になります。


1
これはコンパイルされません:「ラムダ式を暗黙的に型指定されたローカル変数に割り当てることはできません」
Dave Bish 2012年

@デイブ:興味深いことに、その制限について知りませんでした。更新されました、ありがとう!
Dave Swersky 2012年

8

小さなヘルパー関数とジェネリックスを使用すると、コンパイラーに型を推測させ、少し短くすることができます。

public static TOut FuncInvoke<TOut>(Func<TOut> func)
{
    return func();
}

var temp = FuncInvoke(()=>"test");

補足:匿名型を返すことができるので、これも便利です。

var temp = FuncInvoke(()=>new {foo=1,bar=2});

面白いテクニック。これは実行時のオーバーヘッドを追加しますか、それともコンパイル時にすべてですか?
toolmakerSteve 2017

@ToolmakerSteve:私の推測では、実行時のオーバーヘッドがわずかに追加されます(匿名メソッドへの呼び出しが別のメソッド内にラップされます)-ただし、FuncInvokeメソッドが定義された場所(場所と同じアセンブリ)にも依存すると思われますコンパイラが「インライン」できるようなものである可能性があるため、別のアセンブリなどと呼ばれています。これは、簡単なテストプログラムを作成し、コンパイルして、結果のILを分解することで人々が答える種類の質問です。
ダニエルスコット

@ToolmakerSteveパフォーマンスへの影響に関する最後の「推測」に続いて、これがパフォーマンスに与える最悪の場合の影響でさえ、事実上ゼロになると付け加えます(非仮想の静的メソッドへの1つの追加関数呼び出し)。この手法を使用している人は、ラムダを投げているため、そうしている可能性があります。つまり、おそらくどこかで少なくとも2つのLINQ拡張メソッドを使用しているため、1つの追加の関数呼び出しよりもパフォーマンスが10万倍も悪くなるような方法で、いくつかのLINQメソッドを誤ってチェーンした可能性はかなり高いです。 ;)
ダニエルスコット

5

引数付きの匿名メソッドを使用できます:

int arg = 5;

string temp = ((Func<int, string>)((a) => { return a == 5 ? "correct" : "not correct"; }))(arg);

できますが、これが質問に対する答えである方法を説明してください。
toolmakerSteve 2017

2

匿名メソッドは、funcデリゲートを使用して値を返すことができます。これは、匿名メソッドを使用して値を返す方法を示した例です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {


        static void Main(string[] args)
        {
            Func<int, int> del = delegate (int x)
              {
                  return x * x;

              };

            int p= del(4);
            Console.WriteLine(p);
            Console.ReadLine();
        }
    }
}

0

これは、C#8を使用した別の例です(並列タスクをサポートする他の.NETバージョンでも機能する可能性があります

using System;
using System.Threading.Tasks;

namespace Exercise_1_Creating_and_Sharing_Tasks
{
    internal static class Program
    {
        private static int TextLength(object o)
        {
            Console.WriteLine($"Task with id {Task.CurrentId} processing object {o}");
            return o.ToString().Length;
        }

        private static void Main()
        {
            const string text1 = "Welcome";
            const string text2 = "Hello";

            var task1 = new Task<int>(() => TextLength(text1));
            task1.Start();

            var task2 = Task.Factory.StartNew(TextLength, text2);

            Console.WriteLine($"Length of '{text1}' is {task1.Result}");
            Console.WriteLine($"Length of '{text2}' is {task2.Result}");

            Console.WriteLine("Main program done");
            Console.ReadKey();
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.