2010-07-26 11 views
5

Trong CLR qua C# ấn bản thứ ba có một ví dụ mà tôi không thể dường như có ý nghĩa của:mâu và Co-sai - CLR thông qua C#

Ý nghĩa bất biến rằng tham số loại generic không thể thay đổi . Tôi chỉ hiển thị các loại thông số bất biến kiểu cho đến nay trong chương này. n

Biến đổi có nghĩa là tham số loại chung có thể thay đổi từ một lớp thành lớp bắt nguồn từ nó. Trong C#, bạn cho biết contravariant loại chung thông số với trong từ khóa.

Thông số loại chung biến thể chỉ có thể xuất hiện ở vị trí nhập chẳng hạn như đối số của phương pháp. n Covariant Có nghĩa là đối số loại chung có thể thay đổi từ một lớp thành một trong các lớp cơ sở của nó. Trong C#, bạn cho biết covariant loại chung thông số với từ khóa từ khóa. Các thông số chung loại biến thể có thể chỉ xuất hiện ở các vị trí đầu ra như vậy làm kiểu trả về của phương thức.

Tác giả sau đó tiếp tục đưa ra ví dụ này:

public delegate TResult Func<in T, out TResult>(T arg); 

Ở đây, chung chung kiểu tham số T được đánh dấu bằng trong từ khóa, làm cho nó contravariant; và chung loại tham số TResult được đánh dấu bằng các ra từ khóa, làm cho nó hiệp biến

Đây là nơi tôi chạy vào vấn đề ở trang sau (292), sau đó ông đi vào nói điều ngược lại khi sử dụng giao diện.

Khi sử dụng các đại biểu rằng một vài tham số chung chung và trở về giá trị, nó được khuyến khích để luôn xác định từ khóa trong và ngoài cho contravariance và hiệp phương sai bất cứ khi nào> có thể, như làm điều này không có tác động xấu và cho phép đại biểu của bạn để được sử dụng trong nhiều tình huống hơn. Giống như các đại biểu, một giao diện với các tham số kiểu chung có thể có các tham số kiểu của nó là contravariant hoặc covariant. Dưới đây là một ví dụ về một giao diện với một contravariant> generic tham số loại:

public interface IEnumerator<out T> : IEnumerator { 
Boolean MoveNext(); 
T Current { get; } 
} 

Kể từ khi T là contravariant, nó có thể có biên dịch đoạn mã sau và chạy> thành công:

// This method accepts an IEnumerable of any reference type 
Int32 Count(IEnumerable<Object> collection) { ... } 
... 
// The call below passes an IEnumerable<String> to Count 
Int32 c = Count(new[] { "Grant" }); 

Trong ví dụ thứ hai, ông sử dụng từ khóa ngoài (IEnumerator<out T>) và sau đó gọi nó là contravariant. Đây có phải là chính xác hoặc tôi thiếu một cái gì đó.Có một sự khác biệt xác định một contravariant & covariant trong một giao diện? I have been to Oreilly's website regarding this book and this is not listed.

+0

Điều quan trọng cần lưu ý là thiết kế của 'Delegate.Combine' về cơ bản không tương thích với phương sai. Nếu một thường trình có trường ban đầu-null của kiểu ủy nhiệm 'Action ', và nó cố gắng 'Kết hợp' nó với một' Hành động ', trường loại' Hành động 'sẽ giữ một tham chiếu đến một' Hành động ' . Nếu một sau đó cố gắng 'Kết hợp' với' Action ', nỗ lực sẽ thất bại. Vì lý do này, các loại đại biểu mà có thể được sử dụng với 'Kết hợp' không nên là biến thể và cũng không thể so sánh được. Các loại đại biểu quá xấu không xác định phương thức 'Kết hợp' của riêng chúng, vì ... – supercat

+0

... phương thức' Hành động .Combine' có thể đã thực hiện an toàn 'Hành động 'và chuyển nó thành loại' Hành động ', biết rằng kết quả của một chuyển đổi như vậy sẽ chỉ được sử dụng bởi mã mà sẽ ăn nó một' Cat'. – supercat

Trả lời

20

out = hiệp biếnin = contravariant.

Bất kỳ từ nào đối diện là một sai lầm trong cuốn sách của tôi mà tôi sẽ sửa trong một ấn bản sau này.

+6

Wow - chào mừng bạn đến với SO, Jeffrey! –

+8

Bạn biết bạn vừa mới kiểm tra phiên bản của nhà phát triển của khách sạn California, phải không? –

+0

Rượu sâm banh hồng trên băng, có ai không? –

8

Đó là một sai lầm. Đó chắc chắn là một ví dụ về hiệp phương sai. Không có sự khác biệt về ý nghĩa hiệp phương sai và đối nghịch giữa các đại biểu và giao diện.

Tôi đề nghị bạn gửi email cho O'Reilly để báo cáo lỗi.

+1

Hoặc tác giả sẽ đến và trả lời trực tiếp ... ':)' – jjnguy

+1

@Justin: Vâng vâng, đó luôn là một lựa chọn;) –

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