คำอธิบายของ Func


90

ฉันสงสัยว่ามีใครสามารถอธิบายได้ว่าอะไรFunc<int, string>คืออะไรและใช้อย่างไรกับตัวอย่างที่ชัดเจน

คำตอบ:


146

คุณคุ้นเคยกับผู้ได้รับมอบหมายโดยทั่วไปหรือไม่? ฉันมีหน้าเกี่ยวกับผู้รับมอบสิทธิ์และเหตุการณ์ที่อาจช่วยได้หากไม่มีแม้ว่าจะมุ่งเน้นไปที่การอธิบายความแตกต่างระหว่างทั้งสอง

Func<T, TResult>เป็นเพียงผู้รับมอบสิทธิ์ทั่วไป - ค้นหาความหมายในสถานการณ์เฉพาะใด ๆ โดยการแทนที่พารามิเตอร์ type ( TและTResult) ด้วยอาร์กิวเมนต์ประเภทที่เกี่ยวข้อง( intและstring) ในการประกาศ ฉันยังเปลี่ยนชื่อเพื่อหลีกเลี่ยงความสับสน:

string ExpandedFunc(int x)

กล่าวอีกนัยหนึ่งFunc<int, string>คือ delegate ซึ่งแสดงถึงฟังก์ชันที่รับintอาร์กิวเมนต์และส่งคืน a string.

Func<T, TResult>มักใช้ใน LINQ ทั้งสำหรับการคาดการณ์และเพรดิเคต (ในกรณีหลังTResultคือเสมอbool) ตัวอย่างเช่นคุณสามารถใช้ a Func<int, string>เพื่อแสดงลำดับของจำนวนเต็มเป็นลำดับของสตริง โดยปกติแล้วนิพจน์ Lambdaจะใช้ใน LINQ เพื่อสร้างผู้รับมอบสิทธิ์ที่เกี่ยวข้อง:

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);
}

ผลลัพธ์:

Value=3
Value=7
Value=10

3
"กล่าวอีกนัยหนึ่งก็คือผู้รับมอบสิทธิ์ซึ่งแสดงถึงฟังก์ชันที่รับอาร์กิวเมนต์ int และส่งคืนสตริง" เพื่อหลีกเลี่ยงความสับสนสำหรับผู้อื่นฉันจะชี้แจงให้ชัดเจนว่าคุณกำลังพูดถึง Func <int, string> ที่นี่ไม่ใช่ Func <T, TResult> จะเห็นได้ชัดถ้าคุณเข้าใจประเภททั่วไปและผู้รับมอบสิทธิ์ แต่สำหรับผู้ที่ไม่ได้เป็น Func <int, string> ที่ kan มอบหมายให้กับฟังก์ชันที่รับอาร์กิวเมนต์ int และส่งคืนสตริง
Napster ตัวจริง

จะชี้แจงเมื่อฉันกลับมาใช้พีซีในภายหลัง
Jon Skeet

2
ฉันคิดว่าสิ่งนี้ไม่ชัดเจนเท่าคำอธิบายและตัวอย่างของ MSDN ฉันคิดว่าคุณควรเพิ่มข้อมูลเกี่ยวกับวิธีการที่พารามิเตอร์ประเภทสุดท้ายเป็นประเภทการส่งคืน - ชี้แจงว่า Func <int, int, string> ส่งคืนสตริงและใช้เวลา 2 ints ที่ช่วยชี้แจง. ไม่มีอะไรเป็นส่วนตัว - ฉันไม่คิดว่ามันชัดเจนพอ
TheSoftwareJedi

11
คุณจะลงคะแนนทุกคำตอบที่คุณคิดว่าไม่เป็นประโยชน์เท่าที่คุณชื่นชอบหรือไม่? คำตอบนี้ไม่เป็นประโยชน์คุณคิดว่า? คุณคิดว่าบางทีการมองสิ่งต่างๆมากกว่าหนึ่งวิธีอาจไม่ใช่ความคิดที่แย่
Jon Skeet

8
@TheSoftwareJedi: ไม่มีแน่นอนไม่มีเหตุผลที่จะใช้ downvote ของคุณเป็นการส่วนตัว - ความจริงที่ว่าคุณไม่ downvote ด้วยเหตุผลส่วนตัวในวันเสาร์และแล้วก็เกิดขึ้นจะเข้ามาในหัวข้อนี้หลังจากที่เราเคยมีการอภิปรายยาวบนอีเมลเกี่ยวกับพฤติกรรมที่เหมาะสม เป็นเรื่องบังเอิญทั้งหมดใช่หรือไม่?
Jon Skeet

40

Func<int, string>กิน ints และผลตอบแทนสตริง ดังนั้นสิ่งที่กิน ints และส่งคืนสตริง? แล้วนี่ ...

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

ที่นั่นฉันเพิ่งสร้างฟังก์ชันที่กิน ints และส่งคืนสตริง ฉันจะใช้มันอย่างไร?

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"

ฉันรู้ว่าไม่เซ็กซี่มาก แต่นั่นเป็นแนวคิดง่ายๆที่มีกลเม็ดมากมาย ตอนนี้เรามาใช้ Func แทน

Func<int, string> fnc = IntAsString;

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

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

แทนที่จะเรียก IntAsString กับสมาชิกแต่ละคนฉันสร้างการอ้างอิงถึงมันที่เรียกว่า fnc (การอ้างอิงถึงวิธีการเหล่านี้เรียกว่าตัวแทน ) และใช้สิ่งนั้นแทน (จำไว้ว่า fnc กิน ints และส่งคืนสตริง)

ตัวอย่างเช่นนี้ไม่ได้เซ็กซี่มาก แต่ตันของสิ่งที่ฉลาดคุณจะเห็นอยู่บนพื้นฐานของความคิดที่เรียบง่ายของฟังก์ชั่นที่ได้รับมอบหมายและวิธีการขยาย

หนึ่งในไพรเมอร์ที่ดีที่สุดสำหรับเรื่องนี้ผมเคยเห็นเป็นที่นี่ เขามีตัวอย่างจริงมากขึ้น :)


@Therealnapster ฉันก็ชอบเหมือนกัน แต่ฉันชอบชื่อของคุณมากกว่า
BKSpurgeon

28

มันเป็นผู้รับมอบสิทธิ์ที่จะใช้อย่างใดอย่างหนึ่งเป็นพารามิเตอร์และส่งกลับค่าของชนิดintstring

นี่คือตัวอย่างการใช้งาน:

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
ขอบคุณแอนดรู คุณหมายถึงเขียน func (1) แทน bar (1) หรือเปล่า?
zSynopsis

1

Func<int, string>ยอมรับพารามิเตอร์ค่า int และส่งกลับค่าสตริง นี่คือตัวอย่างที่ไม่จำเป็นต้องใช้วิธีการสนับสนุนเพิ่มเติม

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

หมายเหตุ: ประเภทอ็อบเจ็กต์สุดท้ายใน Func (เช่น "สตริง" ในตัวอย่างนี้) คือประเภทการส่งคืนฟังก์ชัน (กล่าวคือไม่ จำกัด เฉพาะไพรเมทีฟ แต่อ็อบเจ็กต์ใด ๆ ) ดังนั้นFunc<int, bool, float>ยอมรับพารามิเตอร์ค่า int และ bool และส่งกลับค่าลอย

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.