Giải thích về hàm


89

Tôi đã tự hỏi liệu ai đó có thể giải thích nó Func<int, string>là gì và nó được sử dụng như thế nào với một số ví dụ rõ ràng.

Câu trả lời:


145

Bạn có quen thuộc với các đại biểu nói chung? Tôi có một trang về người đại diện và sự kiện có thể hữu ích nếu không, mặc dù nó hướng đến việc giải thích sự khác biệt giữa hai trang này nhiều hơn.

Func<T, TResult>chỉ là một đại biểu chung chung - tìm hiểu ý nghĩa của nó trong bất kỳ tình huống cụ thể nào bằng cách thay thế các tham số kiểu ( TTResult) bằng các đối số kiểu tương ứng ( intstring) trong khai báo. Tôi cũng đã đổi tên nó để tránh nhầm lẫn:

string ExpandedFunc(int x)

Nói cách khác, Func<int, string>là một đại diện đại diện cho một hàm nhận intđối số và trả về a string.

Func<T, TResult>thường được sử dụng trong LINQ, cho cả phép chiếu và vị từ (trong trường hợp sau TResultlà luôn luôn bool). Ví dụ: bạn có thể sử dụng a Func<int, string>để chiếu một chuỗi các số nguyên thành một chuỗi các chuỗi. Biểu thức Lambda thường được sử dụng trong LINQ để tạo các đại biểu có liên quan:

Func<int, string> projection = x => "Value=" + x;
int[] values = { 3, 7, 10 };
var strings = values.Select(projection);

foreach (string s in strings)
{
    Console.WriteLine(s);
}

Kết quả:

Value=3
Value=7
Value=10

3
"Nói cách khác, nó là một đại diện đại diện cho một hàm nhận đối số int và trả về một chuỗi." Để tránh nhầm lẫn cho người khác, tôi sẽ làm rõ rằng bạn đang nói về Func <int, string> ở đây chứ không phải Func <T, TResult>. Rõ ràng là nếu bạn hiểu các kiểu và đại biểu chung chung nhưng đối với những người không hiểu thì Func <int, string> kan sẽ ủy nhiệm cho một hàm nhận đối số int và trả về một chuỗi.
The napster thực sự

Sẽ làm rõ khi tôi quay lại PC sau.
Jon Skeet

2
Tôi nghĩ rằng điều này thực sự không rõ ràng như mô tả và ví dụ của MSDN. Tôi cũng nghĩ bạn nên thêm thông tin về cách param kiểu cuối cùng là kiểu trả về - làm rõ rằng Func <int, int, string> trả về chuỗi và nhận 2 int. Điều đó giúp làm rõ. Không có gì cá nhân - tôi chỉ không nghĩ rằng nó đủ rõ ràng.
TheSoftwareJedi

11
Vì vậy, bạn sẽ từ chối mọi câu trả lời mà bạn cho là không hữu ích như yêu thích cụ thể của bạn? Bạn nghĩ câu trả lời này có ích lợi gì không? Bạn có nghĩ rằng có lẽ có nhiều cách nhìn nhận sự việc không phải là một ý kiến ​​tồi?
Jon Skeet

8
@TheSoftwareJedi: Không, tất nhiên, không có lý do gì để gỡ bỏ phiếu phản đối của cá nhân bạn - thực tế là bạn đã phản đối vì lý do cá nhân vào thứ Bảy và sau đó tình cờ đi vào chủ đề này sau khi chúng tôi thảo luận dài qua email về hành vi phù hợp là hoàn toàn ngẫu nhiên, phải không?
Jon Skeet

40

A Func<int, string>ăn int và trả về chuỗi. Vì vậy, những gì ăn int và trả về chuỗi? Còn cái này thì sao ...

public string IntAsString( int i )
{
  return i.ToString();
}

Ở đó, tôi vừa tạo một hàm ăn int và trả về chuỗi. Tôi sẽ sử dụng nó như thế nào?

var lst = new List<int>() { 1, 2, 3, 4, 5 };
string str = String.Empty;

foreach( int i in lst )
{
  str += IntAsString(i);
}

// str will be "12345"

Tôi biết là không sexy lắm, nhưng đó là ý tưởng đơn giản mà rất nhiều chiêu trò dựa trên. Bây giờ, hãy sử dụng Func thay thế.

Func<int, string> fnc = IntAsString;

foreach (int i in lst)
{
  str += fnc(i);
}

// str will be "1234512345" assuming we have same str as before

Thay vì gọi IntAsString trên mỗi thành viên, tôi đã tạo một tham chiếu đến nó được gọi là fnc (những tham chiếu này đến các phương thức được gọi là đại biểu ) và sử dụng nó thay thế. (Hãy nhớ fnc ăn int và trả về chuỗi).

Ví dụ này không gợi cảm lắm, nhưng rất nhiều thứ thông minh mà bạn sẽ thấy dựa trên ý tưởng đơn giản về các hàm, các đại biểu và các phương thức mở rộng .

Một trong những mồi tốt nhất về thứ này mà tôi đã thấy ở đây . Anh ấy có rất nhiều ví dụ thực tế hơn. :)


@Therealnapster, tôi cũng thích nó nhưng tôi thích tên của bạn hơn.
BKSpurgeon

27

Nó là một ủy nhiệm nhận một intlàm tham số và trả về một giá trị kiểu string.

Đây là một ví dụ về cách sử dụng của nó:

using System;

class Program
{
    static void Main()
    {
        Func<Int32, String> func = bar;

        // now I have a delegate which 
        // I can invoke or pass to other
        // methods.
        func(1);
    }

    static String bar(Int32 value)
    {
        return value.ToString();
    }
}

3
Cảm ơn andrew. Ý của bạn là viết func (1) thay vì bar (1)?
zSynopsis

1

Func<int, string>chấp nhận một tham số giá trị int và trả về một giá trị chuỗi. Đây là một ví dụ trong đó một phương pháp hỗ trợ bổ sung là không cần thiết.

Func<int, string> GetDogMessage = dogAge =>
        {
            if (dogAge < 3) return "You have a puppy!";
            if (dogAge < 7) return "Strong adult dog!";

            return "Age is catching up with the dog!";
        };

string youngDogMessage = GetDogMessage(2);

LƯU Ý: Kiểu đối tượng cuối cùng trong Func (tức là "chuỗi" trong ví dụ này) là kiểu trả về của hàm (nghĩa là không giới hạn ở các nguyên thủy, mà là bất kỳ đối tượng nào). Do đó, Func<int, bool, float>chấp nhận các tham số giá trị int và bool, và trả về một giá trị float.

Func<int, bool, float> WorthlessFunc = (intValue, boolValue) =>
        {
            if(intValue > 100 && boolValue) return 100;

            return 1;
        };
float willReturn1 = WorthlessFunc(21, false);
float willReturn100 = WorthlessFunc(1000, true);

HTH

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.