จะคืนค่าจาก Action () ได้อย่างไร?


95

สำหรับคำตอบสำหรับคำถามนี้การส่ง DataContext ไปสู่ ​​Action ()ฉันจะส่งคืนค่าจากการกระทำ (db) ได้อย่างไร

SimpleUsing.DoUsing(db => { 
// do whatever with db 
}); 

น่าจะชอบมากกว่า:

MyType myType = SimpleUsing.DoUsing<MyType>(db => { 
// do whatever with db.  query buit using db returns MyType.
}); 

คำตอบ:


100

วิธีการคงที่ของคุณควรไปจาก:

public static class SimpleUsing
{
    public static void DoUsing(Action<MyDataContext> action)
    {
        using (MyDataContext db = new MyDataContext())
           action(db);
    }
}

ถึง:

public static class SimpleUsing
{
    public static TResult DoUsing<TResult>(Func<MyDataContext, TResult> action)
    {
        using (MyDataContext db = new MyDataContext())
           return action(db);
    }
}

คำตอบนี้มาจากความคิดเห็นดังนั้นฉันจึงสามารถให้รหัสได้ สำหรับรายละเอียดทั้งหมดโปรดดูคำตอบของ @ sll ด้านล่าง


114

คุณสามารถใช้Func<T, TResult>ผู้รับมอบสิทธิ์ทั่วไป (ดูMSDN )

Func<MyType, ReturnType> func = (db) => { return new MyType(); }

นอกจากนี้ยังมีผู้รับมอบสิทธิ์ทั่วไปที่มีประโยชน์ซึ่งพิจารณาค่าตอบแทน:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- ส่งคืนบูล ( MSDN ) เสมอ

วิธี:

public MyType SimpleUsing.DoUsing<MyType>(Func<TInput, MyType> myTypeFactory)

ผู้รับมอบสิทธิ์ทั่วไป:

Func<InputArgumentType, MyType> createInstance = db => return new MyType();

ดำเนินการ:

MyType myTypeInstance = SimpleUsing.DoUsing(
                            createInstance(new InputArgumentType()));

หรืออย่างชัดเจน:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());

6
@LB - การขอให้ผู้ใช้ Google ไม่สร้างสรรค์ SO มีอยู่เพื่อให้คำตอบที่สมบูรณ์
Kirk Woll

5
@KirkWoll แต่คำตอบให้ส่วนผสมมันไม่ต้องปรุง
LB

9
@LB - จะดีกว่าที่จะทำให้สมบูรณ์ ฉันพบว่าการเปรียบเทียบของคุณน่ากลัว
Kirk Woll

1
@LB ดีกว่าที่จะไม่แสดงความคิดเห็นเนื่องจากคุณไม่ได้เพิ่มมูลค่าอะไรเลย
4thSpace

1
@Shn_Android_Dev - คุณพูดถูก แต่ Action ไม่ใช่สิ่งอำนวยความสะดวกในการคืนค่าแน่นอนว่าเราสามารถหมุนเวียนและสร้างวงล้อใหม่ได้ แต่ความซับซ้อนของรหัสดังกล่าวคุ้มค่าที่จะยึดติดกับ Action เป็นหลักหรือไม่?
sll

15

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

MyType result;

SimpleUsing.DoUsing(db => 
{
  result = db.SomeQuery(); //whatever returns the MyType result
}); 

//do something with result

ใช่สิ่งนี้เรียกว่าการปิด (สิ่งที่เป็นภาษาสนุก ๆ ซึ่งมีให้สำหรับเราเช่นกัน)
sll

4

ใช้Func<T>มากกว่าAction<T>.

Action<T> ทำหน้าที่เหมือนวิธีโมฆะที่มีพารามิเตอร์ประเภท T ในขณะที่ Func<T>ทำงานเหมือนฟังก์ชันที่ไม่มีพารามิเตอร์และส่งคืนอ็อบเจ็กต์ประเภท T

Func<TParameter1, TParameter2, ..., TReturn>หากคุณต้องการพารามิเตอร์ให้กับฟังก์ชั่นของการใช้งาน

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