2008-08-30 57 views
104

Tôi có một phương pháp mà mất đối tượng params [] như:Làm thế nào để vượt qua một đối tượng duy nhất [] để một đối tượng params []

void Foo(params object[] items) 
{ 
    Console.WriteLine(items[0]); 
} 

Khi tôi vượt qua hai mảng đối tượng để phương pháp này, nó hoạt động tốt :

Foo(new object[]{ (object)"1", (object)"2" }, new object[]{ (object)"3", (object)"4" }); 
// Output: System.Object[] 

Nhưng khi tôi vượt qua một đối tượng duy nhất [], nó không mất đối tượng của tôi [] như param đầu tiên, thay vì phải mất nó tất cả các yếu tố như tôi muốn vượt qua từng cái một:

Foo(new object[]{ (object)"1", (object)"2" }); 
// Output: 1, expected: System.Object[] 

Làm cách nào để truyền một đối tượng [] làm đối số đầu tiên cho một mảng params?

Trả lời

82

Một định kiểu đơn giản sẽ đảm bảo trình biên dịch biết những gì bạn có nghĩa là trong trường hợp này.

Foo((object)new object[]{ (object)"1", (object)"2" })); 

Là một mảng là một loại phụ của đối tượng, tất cả đều hoạt động. Bit của một giải pháp kỳ lạ mặc dù, tôi sẽ đồng ý.

+0

cách thông số hoạt động dường như không cần thiết và thiết kế C# tối ưu, cho những gì chúng tôi đã quen với các ngôn ngữ khác. params có thể đã được thực hiện để chỉ chấp nhận một hình thức, và một tính năng lây lan như có thể được thêm vào đó sẽ có lợi cho toàn bộ ngôn ngữ, không chỉ là trường hợp này. ví dụ, chúng ta có thể buộc tất cả các cuộc gọi param là Foo (obj [0], obj [1]), và sau đó có một toán tử spread riêng biệt cho phép Foo (... obj). – Lee

+0

nhận ra tôi đã không nói rõ rằng tôi rất tôn trọng những người quản lý hejlsberg, ông là một trong những nhà thiết kế ngôn ngữ tốt nhất trên thế giới. nhưng chúng ta có thể suy nghĩ về những cải tiến đối với công việc của bất kỳ ai do đủ công nhận, do đó công nghệ. – Lee

3

Bạn cần để đóng gói nó vào đối tượng mảng khác [], như thế này:

Foo(new Object[] { new object[]{ (object)"1", (object)"2" }}); 
1

Một lựa chọn là bạn có thể quấn nó vào mảng khác:

Foo(new object[]{ new object[]{ (object)"1", (object)"2" } }); 

Loại xấu xí, nhưng vì mỗi mục là một mảng, bạn không thể bỏ nó để làm cho vấn đề biến mất ... chẳng hạn như nếu nó là Foo (params object items), thì bạn có thể làm:

Foo((object) new object[]{ (object)"1", (object)"2" }); 

Ngoài ra, bạn có thể thử xác định một ví dụ quá tải của Foo mà chỉ mất một mảng duy nhất:

void Foo(object[] item) 
{ 
    // Somehow don't duplicate Foo(object[]) and 
    // Foo(params object[]) without making an infinite 
    // recursive call... maybe something like 
    // FooImpl(params object[] items) and then this 
    // could invoke it via: 
    // FooImpl(new object[] { item }); 
} 
61

Công cụ sửa đổi thông số params cung cấp cho người gọi cú pháp phím tắt để chuyển nhiều đối số cho một phương thức.Có hai cách để gọi một phương thức với một tham số params:

1) Calling với một mảng của các loại tham số, trong trường hợp từ khóa params không có tác dụng và mảng được truyền trực tiếp đến phương pháp:

object[] array = new[] { "1", "2" }; 

// Foo receives the 'array' argument directly. 
Foo(array); 

2) Hoặc gọi với một danh sách dài các đối số, trong trường hợp trình biên dịch sẽ tự động quấn danh sách các đối số trong một mảng tạm thời và thông qua đó để phương pháp:

// Foo receives a temporary array containing the list of arguments. 
Foo("1", "2"); 

// This is equivalent to: 
object[] temp = new[] { "1", "2"); 
Foo(temp); 


Để vượt qua trong một mảng đối tượng đến một phương pháp với một tham số "params object[]", bạn có thể:

1) Tạo một mảng wrapper bằng tay và thông qua đó trực tiếp đến phương pháp, như đã đề cập bởi lassevk:

Foo(new object[] { array }); // Equivalent to calling convention 1. 

2) Hoặc, đúc lập luận để object, như đề cập bởi Adam, trong trường hợp trình biên dịch sẽ tạo ra các mảng wrapper cho bạn:

Foo((object)array); // Equivalent to calling convention 2. 


Tuy nhiên, nếu mục tiêu của phương pháp này là để xử lý nhiều mảng đối tượng, nó có thể được dễ dàng hơn để khai báo với thông số "params object[][]" rõ ràng. Điều này sẽ cho phép bạn để vượt qua nhiều mảng như các đối số:

void Foo(params object[][] arrays) { 
    foreach(object[] array in arrays) { 
    // process array 
    } 
} 

... 
Foo(new[] { "1", "2" }, new[] { "3", "4" }); 

// Equivalent to: 
object[][] arrays = new[] { 
    new[] { "1", "2" }, 
    new[] { "3", "4" } 
}; 
Foo(arrays); 

Edit: Raymond Chen mô tả hành vi này và làm thế nào nó liên quan đến C# đặc điểm kỹ thuật trong a new post.

1
new[] { (object) 0, (object) null, (object) false } 
7

Đây là giải pháp một dòng liên quan đến LINQ.

var elements = new String[] { "1", "2", "3" }; 
Foo(elements.Cast<object>().ToArray()) 
Các vấn đề liên quan