如何使用匿名方法返回值?

101

这个失败了

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

出现了错误

因为它不是委托类型,所以无法将 lambda 表达式转换为字符串类型

这个错误是什么意思,我该如何解决?


2
为什么当搜索“将匿名函数转换为返回 void 的委托时无法返回值”错误时,这个问题会成为谷歌的第一个结果,明显与此无关? - Calmarius
6个回答

144
问题在于你定义了一个返回字符串的匿名方法,但试图直接将其赋值给字符串。这是一个表达式,当调用时会产生一个字符串,它并不直接是一个字符串。它需要被分配给兼容的委托类型。在这种情况下,最简单的选择是 Func<string>。
Func<string> temp = () => {return "test";};

通过一些类型转换或使用委托构造函数来确定lambda的类型并进行调用,可以在一行代码中完成此操作。

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")();

@4thSpace,可以通过一行代码进行一些邪恶的转换来完成。我更新了我的答案以展示这种方法。 - JaredPar
在这种情况下,只需使用 Func<string> temp = () => "test"; - Gabe
@4thSpace 你不能将int字面量声明为参数,但是你可以使用标识符作为int参数的占位符。(x) => { return "test"; } - JaredPar
Func<string> temp = () => {"test";}; 更加简洁; return 关键字只是语义糖果。 - user152949
如果您读完整个答案,底部是更短的表示方法,无需使用return: Func<string> temp = () => "test"; - ToolmakerSteve
显示剩余8条评论

20

您正在尝试将一个函数委托分配给字符串类型。请尝试以下操作:

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

你现在可以这样执行该函数:

string s = temp();

"s"变量现在将具有值"test"。


8
使用一个小辅助函数和通用类型,您可以让编译器推断出类型,并将其缩短一点:
public static TOut FuncInvoke<TOut>(Func<TOut> func)
{
    return func();
}

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

顺便提一句:这也很好,因为您可以返回匿名类型:

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

1
有趣的技巧。这会增加运行时开销吗,还是全部在编译时完成? - ToolmakerSteve
@ToolmakerSteve:我猜它会增加一点运行时开销(它将一个对匿名方法的调用包装在另一个方法中)-但是,我怀疑它也取决于FuncInvoke方法的定义位置(与调用它的程序集相同还是不同的程序集等),因为编译器可能会“内联”它。这是人们通过编写快速测试程序、编译,然后拆解生成的IL来回答的问题的类型。 - Daniel Scott
@ToolmakerSteve 在上一个“猜测”性能影响的基础上,我想补充一点,即使是最坏的情况下,这对性能的影响也几乎为零(多了一个非虚拟的静态方法调用)。使用这种技术的人可能正在使用 lambda 表达式。这意味着他们可能在某个地方使用了至少几个 LINQ 扩展方法,因此很有可能无意中将几个 LINQ 方法链接在一起,从而导致性能下降 100,000 倍比多一个函数调用更糟糕 ;) - Daniel Scott

7
您可以使用带有参数的匿名方法:
int arg = 5;

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

你可以这样做,但请解释一下为什么这是问题的答案。 - ToolmakerSteve

4
匿名方法可以使用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();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接