如何用匿名方法返回值?


89

这失败了

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

与错误

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

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


当搜索错误“显然将匿名函数转换为void返回委托无法返回值”时,为什么这个问题是Google的第一个结果?
Calmarius

Answers:


136

这里的问题是您已经定义了一个匿名方法,该方法返回a,string但尝试将其直接分配给a string。这是一个表达式,在调用时会产生一个表达式,而string不是直接产生string。需要将其分配给兼容的委托类型。在这种情况下,最简单的选择是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")();

谢谢。因此,没有办法在一行上完成所有操作(包括分配字符串)吗?我想要的值(“ test”,实际上是现实生活中的变量)在另一个lambda内,因此如果我尝试像上面一样定义的话,我会松开范围。
2012年

@ 4thSpace可以在一行中完成一些邪恶的转换。我更新了答案以显示路
JaredPar'5

或者在这种情况下,只需Func<string> temp = () => "test";
加布

或是您的编辑string temp = new Func<string>(() => "test")();
Gabe 2012年

完善!如果我想传递一个int,可以一行显示吗?我试过了,但是没有走:((Func <int,string>)((4)=> {返回“测试”;}))();
4thSpace'5

15

您试图将函数委托分配给字符串类型。试试这个:

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

您现在可以这样执行函数:

string s = temp();

现在,“ s”变量的值将为“ test”。


1
无法编译:“无法将lambda表达式分配给隐式类型的局部变量”
Dave Bish 2012年

@Dave:有趣,不知道该限制。更新,谢谢!
戴夫·斯沃斯基

8

使用一些辅助函数和泛型,可以让编译器推断类型,并将其缩短一点:

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

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

旁注:这也很好,因为您随后可以返回匿名类型:

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

有趣的技术。这会增加运行时的开销,还是全部在编译时?
ToolmakerSteve

@ToolmakerSteve:我的猜测是,这将增加大量的运行时开销(它将对另一个方法的调用包装在另一个方法中)-但是,我怀疑它还取决于FuncInvoke方法的定义位置(与在哪里组装相同)它被称为vs不同的程序集等),因为它可能是编译器可以“内联”的一种东西。人们通过编写快速测试程序,进行编译,然后将生成的IL分离出来来回答这种问题。
丹尼尔·斯科特

@ToolmakerSteve在关于性能影响的最后一个“猜测”之后,我还要补充一点,即使这会对性能产生最坏的影响也几乎为零(对非虚拟的静态方法进行一个额外的函数调用)。任何使用此技术的人都可能这样做,因为他们会乱扔lambda。这意味着他们可能至少在某个地方使用了几种LINQ扩展方法,因此很合理的理由是他们无意中将几种LINQ方法链接在一起,造成的性能损失比一个额外的函数调用差100,000倍。 ;)
Daniel Scott

5

您可以使用带有参数的匿名方法:

int arg = 5;

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

您可以,但是请解释一下这是如何解决问题的。
ToolmakerSteve

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();
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.