2010-01-14 78 views
10

Một số loại CLI đặc biệt từ mscorlib thư viện (ArgIterator, TypedReferenceRuntimeArgumentHandle loại) không thể được sử dụng như các tham số kiểu chung chung để xây dựng các loại/phương pháp chung:C thông số # loại đặc điểm kỹ thuật

void Foo<T>() { } 
void Bar() { Foo<ArgIterator>(); } 

cung cấp các lỗi biên dịch :

error CS0306: The type 'System.ArgIterator' may not be used as a type argument 

Nhưng điều này không được ghi chép gì trong đặc tả C#.

Loại này có phải là một phần của đặc điểm kỹ thuật CLI hay các kiểu này được CLR cung cấp và hành vi được mô tả ở trên không nên được ghi lại tại C# spec?

+2

Và bỏ trống, không quá ngạc nhiên. –

Trả lời

10

Trước hết, Jon là một lần nữa chính xác - những kẻ đang loại rất đặc biệt có giá trị là không mui trần để phản đối, và do đó không thể được được sử dụng làm đối số kiểu. Tất cả các đối số kiểu phải là các kiểu có giá trị được chuyển đổi thành đối tượng.

Để trả lời câu hỏi của bạn về tài liệu:

Không có tính năng đặc biệt nào để xử lý Phương pháp variadic được ghi lại. Chúng không phải là một phần của chính ngôn ngữ C# - việc thực thi tuân thủ ngôn ngữ không bắt buộc để có thể thực hiện interop với các ngôn ngữ hỗ trợ các phương thức variadic. Các tính năng này cũng không được ghi trong MSDN như là một phần của tài liệu biên dịch. Đây không phải là các tính năng "được hỗ trợ chính thức". Đây là điều không may, nhưng chỉ có rất nhiều ngân sách, và tôi nghĩ rằng hầu hết mọi người sẽ đồng ý rằng chúng tôi sẽ làm tốt hơn để viết các tính năng và sửa lỗi hơn là chi tiền cho các tính năng mà 99,99% người dùng của chúng tôi sẽ không bao giờ , đã từng sử dụng ngay cả khi chúng được hỗ trợ, chúng không được hỗ trợ.

Nếu bạn muốn đi làm interop trong C# với phương pháp variadic, bạn đang ở trên của riêng bạn. Chúc may mắn!

+0

Tôi đã suy nghĩ sai về tính năng này là "chính thức". Cảm ơn, Eric! :) – ControlFlow

6

Tôi tin rằng đó là vì các loại này là "đặc biệt" ở chỗ chúng không thể được chuyển đổi thành object; chỉ các loại có thể được chuyển đổi thành object mới có thể được chỉ định làm đối số loại. Điều này cũng đúng với con trỏ.

Tôi không thể tìm thấy nơi tài liệu này được ghi lại (nó được ghi lại cho con trỏ trong 4.4.1) nhưng Eric Lippert đã đề cập đến nó trong một nhận xét vào ngày khác.

Đây có phải là vấn đề đáng quan tâm hay bạn đang cố thực sự làm điều gì đó đang sử dụng loại điều này?

+1

Tất nhiên đây chỉ là sự quan tâm và ví dụ tổng hợp, tôi đã thử nghiệm một số mã chung với tất cả các valuetypes từ mscorlib và thành lập vấn đề này, nhưng không tìm thấy lời giải thích trong C# spec ... Tôi hiểu, rằng loại này rất đặc biệt, ArgIterator là thực sự là một cấu trúc với kích thước khác nhau ... nhưng không có lời giải thích! :) – ControlFlow

1

Tất cả ba ví dụ mà bạn cung cấp là cấu trúc, chứ không phải lớp học, vì vậy tôi nghi ngờ đó là chìa khóa cho vấn đề. Một ví dụ được cung cấp trong tài liệu trên số compiler error message cũng cho biết rằng nếu bạn sử dụng một con trỏ đến một loại trong chung, nó sẽ thất bại.

+0

Structs được cho phép và ArgIterator, cho một, không chứa con trỏ. Tôi đã thử một cấu trúc tùy chỉnh có chứa các lĩnh vực IntPtr và điều này hoạt động tốt. Đấu tranh để xem điều gì gây ra lỗi. Có lẽ nó liên quan đến các phương thức bên ngoài hoặc không an toàn. –

1

Mục 8.2.4 trong số các loại giá trị cuộc gọi CLI spec có thể chứa con trỏ vào các đánh giá ngăn xếp "byref-like" loại và nói rằng chúng không thể được đóng hộp. Nó rõ ràng gọi ra System.RuntimeArgumentHandleSystem.TypedReference làm ví dụ về các loại như vậy nhưng không cung cấp danh sách đầy đủ. Mục 9.4 tiếp tục cho biết rằng các kiểu byref, các kiểu như byref và System.Void không thể được sử dụng để khởi tạo các kiểu generic hoặc các phương thức.

1

Cũng giống như một bình luận, đây là một số thú vị hơn bạn có thể có khi cố gắng để biên dịch mã với loại này mà không phải là chuyển đổi thành đối tượng. Tất cả các phương pháp ở đây xuất hiện dưới dạng gợi ý của Visual Studio khi bạn nhập . (dấu chấm).

ArgIterator.ReferenceEquals(new object(), new object()); // OK; static method inherited from System.Object 

    var strange = default(ArgIterator); 
    strange.End();   // OK; non-virtual method defined in the struct 
    strange.GetHashCode(); // OK; method overridden in the struct 
    strange.ToString();  // compile-time error; method overriden in System.ValueType, inherited but not overridden in the struct 
    strange.GetType();  // compile-time error; non-virtual method inherited from System.Object 
Các vấn đề liên quan