Sự khác biệt giữa <out T>và là <T>gì? Ví dụ:
public interface IExample<out T>
{
...
}
so với
public interface IExample<T>
{
...
}
Sự khác biệt giữa <out T>và là <T>gì? Ví dụ:
public interface IExample<out T>
{
...
}
so với
public interface IExample<T>
{
...
}
Câu trả lời:
Các outtừ khóa trong Generics được sử dụng để biểu thị rằng các loại T trong giao diện là hiệp biến. Xem hiệp phương sai và chống chỉ định để biết chi tiết.
Ví dụ kinh điển là IEnumerable<out T>. Vì IEnumerable<out T>là covariant, bạn được phép làm như sau:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
Dòng thứ hai ở trên sẽ thất bại nếu điều này không đồng biến, mặc dù về mặt logic nó sẽ hoạt động, vì chuỗi xuất phát từ đối tượng. Trước khi phương sai trong các giao diện chung được thêm vào C # và VB.NET (trong .NET 4 với VS 2010), đây là lỗi thời gian biên dịch.
Sau .NET 4, IEnumerable<T>được đánh dấu covariant và trở thành IEnumerable<out T>. Vì IEnumerable<out T>chỉ sử dụng các phần tử bên trong nó và không bao giờ thêm / thay đổi chúng, nên nó an toàn để coi một bộ sưu tập chuỗi vô số như một bộ sưu tập các đối tượng, có nghĩa là nó là đồng biến .
Điều này sẽ không hoạt động với một loại như IList<T>, vì IList<T>có một Addphương pháp. Giả sử điều này sẽ được cho phép:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
Sau đó bạn có thể gọi:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
Tất nhiên, điều này sẽ thất bại - vì vậy IList<T>không thể đánh dấu covariant.
Ngoài ra còn có, btw, một tùy chọn cho in- được sử dụng bởi những thứ như giao diện so sánh. IComparer<in T>, ví dụ, hoạt động theo cách ngược lại. Bạn có thể sử dụng một bê tông IComparer<Foo>trực tiếp như một IComparer<Bar>nếu Barlà một lớp con của Foo, bởi vì IComparer<in T>giao diện là contravariant .
Imagelà một lớp trừu tượng;) Bạn có thể làm new List<object>() { Image.FromFile("test.jpg") };mà không có vấn đề gì, hoặc bạn cũng có thể làm new List<object>() { new Bitmap("test.jpg") };như vậy. Vấn đề với bạn là điều đó new Image()không được phép (bạn cũng không thể làm var img = new Image();được)
IList<object>là một ví dụ kỳ quái, nếu bạn muốn objectbạn không cần thuốc generic.
Để dễ dàng ghi nhớ việc sử dụng invà outtừ khóa (cũng là hiệp phương sai và chống đối), chúng ta có thể hình ảnh kế thừa như gói:
String : Object
Bar : Foo

xem xét,
class Fruit {}
class Banana : Fruit {}
interface ICovariantSkinned<out T> {}
interface ISkinned<T> {}
và các chức năng,
void Peel(ISkinned<Fruit> skinned) { }
void Peel(ICovariantSkinned<Fruit> skinned) { }
Hàm chấp nhận ICovariantSkinned<Fruit>sẽ có thể chấp nhận ICovariantSkinned<Fruit>hoặc ICovariantSkinned<Bananna>vì ICovariantSkinned<T>là giao diện covariant và Bananalà một loại Fruit,
chức năng chấp nhận ISkinned<Fruit>sẽ chỉ có thể chấp nhận ISkinned<Fruit>.
" out T" có nghĩa là loại đó Tlà "covariant". Điều đó hạn chế Tchỉ xuất hiện dưới dạng giá trị trả về (bên ngoài) trong các phương thức của lớp, giao diện hoặc phương thức chung. Hàm ý là bạn có thể truyền kiểu / giao diện / phương thức tương đương với siêu kiểu T.
Ví dụ ICovariant<out Dog>có thể được đúc ICovariant<Animal>.
outthực thi chỉ Tcó thể được trả lại, cho đến khi tôi đọc câu trả lời này. Toàn bộ khái niệm có ý nghĩa hơn bây giờ!
Từ liên kết bạn đã đăng ....
Đối với các tham số loại chung, từ khóa out chỉ định rằng tham số loại là covariant .
EDIT : Một lần nữa, từ liên kết bạn đã đăng
Để biết thêm thông tin, hãy xem Hiệp phương sai và Chống chỉ định (C # và Visual Basic). http://msdn.microsoft.com/en-us/l Library / ee207183.aspx