2009-09-26 30 views
8

Vì vậy, nhiều lần chúng ta có một hàm chấp nhận một IEnumerable hoặc ICollection như một tham số. Trong trường hợp chúng tôi có các mục duy nhất, nhưng không có bộ sưu tập để giữ họ, chúng ta phải tạo ra một bộ sưu tập trước khi chuyển chúng đến chức năng, như:Cách dễ nhất và nhỏ gọn nhất để tạo một số điện thoại IE2umerhoặc ICollection <T> là gì?

T o1, o2, o3; 
Foo(new T[] { o1, o2, o3 }); 

Tôi luôn tạo ra một mảng hoặc một danh sách, như tôi đã thực hiện trong ví dụ cuối cùng. Nhưng tôi tự hỏi, có cách nào tao nhã hơn để tạo IEnumerable hoặc ICollection được yêu cầu không?

Nó sẽ là khá mát mẻ, nếu người ta có thể làm điều này:

Foo({ o1, o2, o3 }); 

Và trình biên dịch sẽ tạo ra bộ sưu tập trừu tượng nhất có thể đó sẽ đáp ứng các nhu cầu của IEnumerable hoặc ICollection (tùy thuộc vào một chức năng chấp nhận).

Dù sao đi nữa, làm thế nào bạn có thể vượt qua o1, o2 và o3 đến một tham số IEnumerable hoặc ICollection?

Trả lời

10

Phiên bản hiện tại (3) C# hỗ trợ một ký hiệu không có loại rõ ràng, ví dụ:

Foo(new [] { o1, o2, o3 }) 

để tạo mảng. Ngoài ra còn có Enumerable.Range của Linq để tạo một dãy số liên tục. Mọi thứ khác phải được thực hiện. Theo tinh thần của Java:

public static IEnumerable<T> AsList<T>(params T[] values) { 
    return values; 
} 

được gọi là như thế này:

Foo(Enumerable.AsList(o1, o2, o3)); 
+1

Tôi đề nghị rằng 'AsList()' không phải là một tên tốt cho một phương pháp mà trả về một 'Enumerable', không phải 'List'! Làm thế nào về 'Enumerable.Create'? –

2

Giả sử Foo hy vọng một IEnumerable <T>, bạn có thể tận dụng lợi thế của kiểu suy luận và làm:

T o1, o2, o3; 
Foo(new []{o1, o2, o3}); 
3

Đôi khi tôi đã sử dụng một phương pháp với một "params" tranh cãi.

Foo(params T[] ts) 

Và nếu tôi đã chết trên IEnumerable tôi chỉ có phương thức đó ủy quyền cho người muốn IEnumerable.

Foo(params T[] ts) { Foo(ts.AsEnumerable()); } 

Bạn phải gọi AsEnumerable hoặc bạn sẽ tái chế.

2

Tạo một mảng và truyền mà có lẽ là cách đơn giản/thanh lịch nhất để thực hiện việc này trong phiên bản hiện tại của C#. Bạn có thể tận dụng tiềm ẩn mảng gõ (ví dụ new[] { ... }, nhưng đó là như xa như nó đi

tôi nghi ngờ bạn đang thực sự tìm kiếm các C# tương đương với F # cú pháp sau:.

let foo = seq [ o1; o2; o3 ] 

mà tạo ra một IEnumerable<T> sẽ lặp qua các phần tử được chỉ định. ('Seq' thực sự là bí danh F # cho 'IEnumerable`, mặc dù F # đã hỗ trợ sẵn cho chúng.)

Thật không may, vì đây là khái niệm chủ yếu về chức năng, có không tương đương với C# - mặc dù ai biết khi nào nó sẽ được thêm vào, vì C# càng trở nên thú vị hơn ctional.

0

Nếu bạn có phương thức lấy mảng làm tham số cuối cùng, có thể có ý nghĩa để đánh dấu tham số params. Điều này cho phép bạn gọi phương thức như thế này:

Foo(o1, o2, o3); 

Tôi tìm thấy điều này đặc biệt hữu ích khi viết một bài kiểm tra đơn vị cho Foo(), bởi vì thường trong một đơn vị kiểm tra các thông số của tôi là riêng biệt như thế này, thay vì trong một mảng.

Tôi khuyên bạn không nên làm điều này nếu có quá tải Foo() không chiếm một mảng ở vị trí đó, vì nó có thể gây nhầm lẫn nhanh chóng.

Tôi mong rằng ngôn ngữ C# cho phép params cho IList<T>:

void Foo(params IList<T> ts) { ... } 
Các vấn đề liên quan