익명 메서드로 값을 반환하는 방법은 무엇입니까?


90

이것은 실패합니다

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

오류와 함께

람다식이 대리자 형식이 아니기 때문에 '문자열'형식으로 변환 할 수 없습니다.

오류의 의미는 무엇이며 어떻게 해결할 수 있습니까?


이 질문이 "무효 반환 대리자로 변환 된 익명 함수는 값을 반환 할 수 없습니다"라는 오류를 검색 할 때 Google의 첫 번째 결과가되는 이유는 분명히 관련이 없습니다.
Calmarius

답변:


136

여기서 문제는 a를 반환하는 익명 메서드를 정의 string했지만 string. 호출 될 때 string직접 생성 되지 않는 표현식입니다 string. 호환되는 대리자 유형에 할당해야합니다. 이 경우 가장 쉬운 선택은Func<string>

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

이 작업은 약간의 캐스팅을 통해 한 줄로 수행하거나 대리자 생성자를 사용하여 람다 형식을 설정 한 다음 호출을 수행 할 수 있습니다.

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")은 다른 람다 안에 있으므로 위에서 정의한대로 정의하려고하면 범위를 잃어 버립니다.
4thSpace

@ 4thSpace 사악한 캐스팅으로 한 줄로 할 수 있습니다. 나는 길을 보여 내 대답을 업데이 트
JaredPar

또는이 경우에는 Func<string> temp = () => "test";.
Gabe

또는 편집의 경우string temp = new Func<string>(() => "test")();
Gabe

완전한! int를 전달하고 싶다면 한 줄로 보여줄 수 있습니까? 나는 이것을 시도했지만 가지 않았다 : ((Func <int, string>) ((4) => {return "test";})) ();
4thSpace

15

문자열 유형에 함수 대리자 를 할당하려고 합니다. 이 시도:

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

이제 다음과 같이 함수를 실행할 수 있습니다.

string s = temp();

"s"변수는 이제 "test"값을 갖습니다.


1
이것은 컴파일되지 않습니다. "암시 적으로 형식화 된 지역 변수에 람다 식을 할당 할 수 없습니다."
Dave Bish

@Dave : 흥미 롭군요. 그 한계에 대해 몰랐습니다. 감사합니다!
Dave Swersky

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 메서드가 정의 된 위치 (어디에서와 동일한 어셈블리)에 따라 달라질 수 있습니다. 컴파일러가 "인라인" 수있는 종류 일 있기 때문에 다른 어셈블리 등에 대해 호출되고 있습니다 . 이것은 사람들이 빠른 테스트 프로그램을 작성하고 컴파일 한 다음 결과 IL을 선택함으로써 대답하는 종류의 질문입니다.
Daniel Scott

@ToolmakerSteve 성능 영향에 대한 마지막 "추측"에 이어, 이것이 성능에 미치는 최악의 영향도 사실상 nil (비가 상 정적 메서드에 대한 추가 함수 호출 하나)이 될 것이라고 덧붙였습니다. 이 기술을 사용하는 사람은 람다를 던지기 때문에 그렇게 할 가능성이 높습니다. 즉, 어딘가에서 적어도 두 개의 LINQ 확장 메서드를 사용하고 있기 때문에 한 번의 추가 함수 호출보다 100,000 배 더 나쁜 성능을 저하시키는 방식으로 두 개의 LINQ 메서드를 실수로 함께 연결했을 가능성이 높습니다. ;)
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();
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.