Làm thế nào để trả về giá trị với phương thức ẩn danh?


89

Điều này không thành công

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

với lỗi

Không thể chuyển đổi biểu thức lambda thành kiểu 'chuỗi' vì nó không phải là kiểu đại biểu

Lỗi có nghĩa là gì và tôi có thể giải quyết nó như thế nào?


Tại sao câu hỏi này là kết quả đầu tiên trong Google khi tìm kiếm lỗi "chức năng ẩn danh được chuyển đổi thành một đại biểu trả về void không thể trả lại giá trị" khi rõ ràng không liên quan gì đến nó?
Calmarius

Câu trả lời:


136

Vấn đề ở đây là bạn đã xác định một phương thức ẩn danh trả về a stringnhưng đang cố gắng gán nó trực tiếp cho a string. Đó là một biểu thức mà khi được gọi sẽ tạo ra stringnó không trực tiếp a string. Nó cần được chỉ định cho một loại đại biểu tương thích. Trong trường hợp này, sự lựa chọn dễ dàng nhất làFunc<string>

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

Điều này có thể được thực hiện trong một dòng bằng cách ép kiểu một bit hoặc sử dụng hàm tạo ủy nhiệm để thiết lập kiểu lambda theo sau là một lời gọi.

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

Lưu ý: Cả hai mẫu có thể được rút gọn thành biểu mẫu thiếu { return ... }

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

Cảm ơn. Vì vậy, không có cách nào để làm mọi thứ trên một dòng (bao gồm cả việc gán chuỗi)? Giá trị tôi muốn ("test", thực sự là một biến trong cuộc sống thực) nằm bên trong một lambda khác, vì vậy tôi sẽ mất phạm vi nếu tôi cố gắng xác định như bạn có ở trên.
4thSpace

@ 4thSpace nó có thể được thực hiện trong một dòng với một số đúc ác. Tôi đã cập nhật câu trả lời của mình để chỉ đường
JaredPar

Hoặc trong trường hợp này, chỉ Func<string> temp = () => "test";.
Gabe

Hoặc trong trường hợp chỉnh sửa của bạn,string temp = new Func<string>(() => "test")();
Gabe

Hoàn hảo! Nếu tôi muốn chuyển vào một int, bạn có thể chỉ ra điều đó trong một dòng không? Tôi đã thử điều này nhưng không thành công: ((Func <int, string>) ((4) => {return "test";})) ();
4thSpace

15

Bạn đang cố gắng gán một đại biểu hàm cho một kiểu chuỗi. Thử đi:

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

Bây giờ bạn có thể thực thi hàm do đó:

string s = temp();

Biến "s" bây giờ sẽ có giá trị "test".


1
Điều này không biên dịch: "Không thể gán biểu thức lambda cho một biến cục bộ được nhập ngầm"
Dave Bish

@Dave: Thật thú vị, không biết về hạn chế đó. Đã cập nhật, cảm ơn!
Dave Swersky

8

Sử dụng một hàm trợ giúp nhỏ và các số liệu chung, bạn có thể cho phép trình biên dịch suy ra loại và rút ngắn nó một chút:

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

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

Lưu ý phụ: điều này cũng rất hay vì sau đó bạn có thể trả về một kiểu ẩn danh:

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

Kỹ thuật thú vị. Điều này có thêm chi phí thời gian chạy hay tất cả chỉ có tại thời gian biên dịch?
ToolmakerSteve

@ToolmakerSteve: Dự đoán của tôi là nó sẽ thêm một bit teeeeensy chi phí thời gian chạy (nó gói một lệnh gọi đến một phương thức ẩn danh bên trong một phương thức khác) - tuy nhiên, tôi nghi ngờ nó cũng sẽ phụ thuộc vào nơi phương thức FuncInvoke được xác định (cùng một hội với nơi nó đang được gọi so với lắp ráp khác nhau, v.v.), vì nó có thể là loại thứ mà trình biên dịch có thể "nội tuyến". Đây là loại câu hỏi mà mọi người trả lời bằng cách viết một chương trình kiểm tra nhanh, biên dịch và sau đó chọn IL kết quả.
Daniel Scott

@ToolmakerSteve Tiếp theo từ "phỏng đoán" cuối cùng đó ở tác động đến hiệu suất, tôi sẽ nói thêm rằng ngay cả tác động trong trường hợp xấu nhất mà điều này gây ra đối với hiệu suất cũng sẽ gần như không (một lệnh gọi hàm bổ sung, đối với một phương thức tĩnh, không ảo). Bất cứ ai sử dụng kỹ thuật này đều có thể làm như vậy vì họ đang ném những con lambdas xung quanh. Điều đó có nghĩa là họ có thể đang sử dụng ít nhất một vài phương thức mở rộng LINQ ở đâu đó, vì vậy tỷ lệ thuận lợi là công bằng mà nói, họ đã vô tình xâu chuỗi một vài phương thức LINQ lại với nhau theo cách gây hại cho hiệu suất kém hơn 100.000 lần so với một lệnh gọi hàm bổ sung ;)
Daniel Scott

5

bạn có thể sử dụng phương pháp ẩn danh với đối số:

int arg = 5;

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

Bạn có thể, nhưng vui lòng giải thích cách đây là câu trả lời cho câu hỏi.
ToolmakerSteve

2

Một phương thức ẩn danh có thể trả về một giá trị bằng cách sử dụng một đại biểu func. Đây là một ví dụ mà tôi đã chỉ ra cách trả về giá trị bằng phương thức ẩn danh.

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

Đây là một ví dụ khác sử dụng C # 8 ( cũng có thể hoạt động với các phiên bản .NET khác hỗ trợ các tác vụ song song )

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();
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.