2012-01-26 31 views
29

Tôi có một phương pháp có sử dụng các từ khóa params, như vậy:Tại sao truyền null cho một kết quả phương thức params trong một mảng tham số null?

private void ParamsMethod(params string[] args) 
{ 
    // Etc... 
} 

Sau đó, tôi gọi là phương pháp sử dụng kết hợp khác nhau của các đối số:

      // Within the method, args is... 
ParamsMethod();    // - a string array with no elements 
ParamsMethod(null);   // - null (Why is this?) 
ParamsMethod((string)null); // - a string array with one element: null 
ParamsMethod(null, null); // - a string array with two elements: null and null 
ParamsMethod("s1");   // - a string array with one element: "s1" 
ParamsMethod("s1", "s2"); // - a string array with two elements: "s1" and "s2" 

Tôi hiểu tất cả các trường hợp, trừ cái thứ hai. Ai đó có thể giải thích lý do tại sao ParamsMethod(null) gây ra argsnull, thay vì một mảng có một phần tử null không?

+0

Bây giờ bạn đã biết câu trả lời, bạn có thể làm việc trong câu đố này. Bạn có hai phương thức, 'void M (object) {}' và 'void M (params object []) {}'. Bạn gọi là 'M (null)'.Quá tải nào được chọn, cái gì được truyền cho nó, và tại sao? –

+2

Tôi đã gặp phải điều này trước đây. Tôi nghĩ rằng chỉ cần đổi tên một trong những phương pháp. :) – FishBasketGordo

Trả lời

29

Thông số params chỉ nhằm cung cấp cách thuận tiện để chỉ định giá trị - bạn vẫn có thể chuyển trực tiếp tham chiếu mảng.

Hiện tại, null có thể chuyển đổi thành string[] hoặc string, vì vậy cả hai cách diễn giải đều hợp lệ - tùy thuộc vào thông số được ưu tiên. Các trạng thái đặc tả trong phần 10.6.1.4 rằng:

  • Đối số đưa ra cho một mảng tham số có thể là một biểu hiện duy nhất đó là mặc nhiên chuyển đổi thành kiểu mảng tham số. Trong trường hợp này, mảng tham số hoạt động chính xác như tham số giá trị.

  • Ngoài ra, [...]

Nói cách khác, kiểm tra trình biên dịch để xem liệu đối số có giá trị như các loại tham số "bình thường" đầu tiên, và chỉ xây dựng một mảng nếu nó hoàn toàn phải.

+4

Ngoài ra, cần lưu ý rằng nhiều phương thức lấy một mảng tham số cũng sẽ có quá tải cho (đối tượng), (đối tượng, đối tượng) và (đối tượng, đối tượng, đối tượng) - Điều này là tránh chi phí xây dựng mảng đối tượng chỉ cho một vài đối tượng, vì những sự quá tải này sẽ được so khớp trước tiên. –

3

Lý do cho điều này là bạn có thể chuyển một mảng của loại phù hợp đến đối số params. Vì null có thể được chuyển đổi thành bất kỳ loại nào và cú pháp mảng được ưu tiên, bạn nhận được null làm giá trị của thông số của mình.

Rõ ràng hãy đúc nó vào string, tất nhiên, làm cho nó trở thành một phần tử của mảng chứ không phải chính mảng đó.

Bạn có thể thử nó và xem:

private void DoSomething(params IEnumerable[] arr) { 
    // ... 
} 

... 

DoSomething(new IEnumerable[] {new int[] {}}); // arr[0] isn't IEnumerable[], it's int[]. 

And here's an online demo.

3

Bạn có thể truyền một mảng tới một tham số params - trên thực tế, nó là một lợi thế (Tức là nếu bạn vượt qua một đối tượng [] để một phương thức lấy đối tượng param [], nó là toàn bộ tham số, không chỉ là phần tử đơn lẻ). Null là hợp lệ như một nhiệm vụ cho một mảng, vì vậy - ràng buộc đó thắng.

Về cơ bản, bạn sẽ rõ ràng hơn.

7

Xem thông số kỹ thuật C#, phần 10.6.1.4 mảng Parameter:

Một mảng tham số cho phép đối số được quy định tại một trong hai cách trong một invocation phương pháp:

  • Lý lẽ đưa ra cho một mảng tham số có thể là một biểu hiện duy nhất đó là ngầm chuyển đổi (§6.1) thành kiểu mảng tham số. Trong trường hợp này, mảng tham số hoạt động chính xác như tham số giá trị.
  • Hoặc, lời gọi có thể chỉ định không hoặc nhiều đối số cho mảng tham số, trong đó mỗi đối số là một biểu thức chuyển đổi hoàn toàn (§6.1) thành kiểu phần tử của mảng tham số. Trong trường hợp này, lời gọi tạo ra một thể hiện của kiểu mảng tham số với độ dài tương ứng với số lượng đối số, khởi tạo các phần tử của thể hiện mảng với các giá trị đối số đã cho và sử dụng cá thể mảng mới được tạo làm đối số thực tế.

Kể từ null là mặc nhiên chuyển đổi thành string[], nó sẽ được sử dụng như mảng.

Hơn nữa:

Khi thực hiện giải quyết tình trạng quá tải, một phương pháp với một mảng tham số có thể được áp dụng một trong hai hình thức bình thường của nó hoặc dưới hình thức mở rộng của nó (§7.5.3.1). Dạng mở rộng của một phương thức chỉ có sẵn nếu hình thức bình thường của phương thức này không áp dụng được và chỉ khi một phương thức có cùng chữ ký với dạng mở rộng chưa được khai báo trong cùng một kiểu.

đó quy định rõ các trình biên dịch thực sự đầu tiên cố gắng sử dụng phương pháp này với một mảng luận (hình thức bình thường) trước khi nó cố gắng sử dụng các lập luận như một mảng yếu tố (mẫu mở rộng).

2

Từ đặc tả ngôn ngữ:

Một mảng tham số cho phép đối số được quy định tại một trong hai cách trong một invocation phương pháp:

  • Đối số đưa ra cho một mảng tham số có thể là một biểu thức đơn lẻ được chuyển đổi hoàn toàn (§6.1) thành kiểu mảng tham số. Trong trường hợp này, mảng tham số hoạt động chính xác như tham số giá trị. Ngoài ra, lời gọi có thể chỉ định không hoặc nhiều đối số cho mảng tham số, trong đó mỗi đối số là một biểu thức chuyển đổi hoàn toàn (§6.1) thành kiểu phần tử của mảng tham số. Trong trường hợp này, lời gọi tạo ra một thể hiện của kiểu mảng tham số với độ dài tương ứng với số lượng đối số, khởi tạo các phần tử của thể hiện mảng với các giá trị đối số đã cho và sử dụng cá thể mảng mới được tạo làm đối số thực tế.

Kể từ null trong ParamsMethod(null) có thể được ngầm chuyển đổi sang (string[])null, nguyên tắc đầu tiên là một trong đó được áp dụng.

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