2009-08-15 35 views
134

Tôi có thể chuyển một phương thức có tham số ngoài làm Func không?Func <T> với tham số ngoài

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 nên ra sẽ không biên dịch ở đó, và gọi listFunction đòi hỏi một int và sẽ không cho phép một trong.

Có cách nào để làm điều này?

Trả lời

192

refout không nằm trong định nghĩa kiểu tham số, do đó bạn không thể sử dụng được xây dựng trong Func đại biểu để vượt qua refout đối số. Tất nhiên, bạn có thể khai báo đạ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); 
+13

Trong trường hợp người khác bị nhầm lẫn như tôi, bạn không * có * để gọi đại biểu của bạn "Func" như người được cài sẵn ... – Dunc

+0

@Dunc - Đã sửa lỗi. Tôi đã thực sự bối rối vì nó không phải là bình luận của bạn. –

+5

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 bạn) có thể đánh dấu 'T' là contravariant và' V' là biến thể. Tuy nhiên, vì một tham số ('output') của kiểu' U' được truyền *** bởi tham chiếu ***, 'U' không thể được đánh dấu đồng hoặc contravariant và phải duy trì" bất biến ". Vì vậy, hãy xem xét "đại biểu công cộng V MyDelegate (T đầu vào, ra đầu ra U),' nếu bạn sử dụng C# 4 hoặc sau đó. –

19

Tại sao không tạo lớp học để đóng gói các kết quả?

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

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

9

Gia đình Func của các đại biểu (hoặc Action cho 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) 

, vv Các đại biểu như vậy có thể có tham số out/ref, do đó, trong trường hợp của bạn, nó chỉ là vấn đề thực hiện tùy chỉnh của chính bạn 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ĩ đến 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ỉ với hai tham số. Chúng tôi thậm chí không chạm vào ref. Nó thực sự sẽ rườm rà và gây nhầm lẫn cho các nhà phát triển.

+1

Lưu ý rằng hàm quá tải hàm C# không thể phân biệt giữa 'đại biểu TRESult Func (T1 obj, T2 obj)' và 'đại biểu TRESult Func (trong T1 obj, T2 obj)'. Vì vậy, bên cạnh số lượng các tên quá tải biểu tượng là một lý do khác cho lý do tại sao Microsoft không thể thêm những quá tải của 'Func'. –

Các vấn đề liên quan