Func <T> với tham số out


167

Tôi có thể truyền một phương thức với tham số out là Func không?

public IList<Foo> FindForBar(string bar, out int count) { }

// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }

Func cần một loại vì vậy sẽ không biên dịch ở đó và gọi danh sách Chức năng yêu cầu một số nguyên và sẽ không cho phép thoát ra.

Có cách nào để làm việc này không?

Câu trả lời:


228

refoutkhông phải là một phần của định nghĩa tham số loại, do đó bạn không thể sử dụng Funcủy nhiệm tích hợp để truyền refoutđối số. Tất nhiên, bạn có thể tuyên bố đại biểu của riêng bạn nếu bạn muốn:

delegate V MyDelegate<T,U,V>(T input, out U output);

7
Trong C # 4 (2010) và sau đó (không được phát hành khi bạn viết câu trả lời của mình), có thể đánh dấu Tlà chống chỉ định và Vlà covariant. Tuy nhiên, vì một tham số ( output) của loại Uđược truyền bằng tham chiếu , Ukhông thể được đánh dấu co-hoặc contravariant và phải duy trì "bất biến". Vì vậy, hãy xem xét public delegate V MyDelegate<in T, U, out V>(T input, out U output);nếu bạn sử dụng C # 4 trở lên.
Jeppe Stig Nielsen


24

Tại sao không tạo một lớp để đóng gói kết quả?

public class Result
{
     public IList<Foo> List { get; set; }
     public Int32 Count { get; set; }
}

13

Các Funcgia đình của các đại biểu (hoặc Actioncho rằng vấn đề) là gì, nhưng loại đại biểu đơn giản tuyên bố như

//.NET 4 and above
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T obj)

//.NET 3.5
public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)

v.v ... Các đại biểu như vậy có thể có các tham số out / ref, vì vậy trong trường hợp của bạn, vấn đề chỉ là tự thực hiện tùy chỉnh như các câu trả lời khác đã chỉ ra. Về lý do tại sao Microsoft không đóng gói này theo mặc định, hãy nghĩ về số lượng kết hợp tuyệt đối mà nó sẽ yêu cầu.

delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)

chỉ cho hai tham số. Chúng tôi thậm chí không chạm vào ref. Nó thực sự sẽ cồng kềnh và khó hiểu cho các nhà phát triển.


2
Lưu ý rằng quá tải chức năng C # không thể phân biệt giữa delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj). Vì vậy, bên cạnh số lượng tên biểu tượng quá tải là một lý do khác cho lý do tại sao Microsoft không thể thêm các quá tải này Func.
Kasper van den Berg

Ai đó có thể giới thiệu cho tôi một bài viết MSDN về các đại biểu ở trên không?
Su Llewellyn

@SuLlewellyn tôi couldnt tìm thấy bài viết MSDN gốc, nhưng bạn có thể thử: docs.microsoft.com/en-us/dotnet/api/... , docs.microsoft.com/en-us/dotnet/api/...
nawfal

0

Bạn có thể gói nó trong một phương thức lambda / ủy nhiệm / chức năng / hiển thị giao diện phù hợp và được gọi là FindForBar, nhưng tôi nghi ngờ rằng FindForBar được coi là một tham số ngoài lý do, vì vậy bạn cần chắc chắn ném thông tin đó đi ok / safe / mong muốn / đã có kết quả đúng (bạn cần chắc chắn về điều này ngay cả khi bạn có thể trực tiếp vượt qua trong FindForBar).

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.