У чому різниця між <out T>і <T>? Наприклад:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
У чому різниця між <out T>і <T>? Наприклад:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
Відповіді:
outКлючове слово в відтворених використовується для позначення того, що тип Т в інтерфейсі коваріантен. Докладніше див. Коваріація та противаріантність .
Класичний приклад - це IEnumerable<out T>. Оскільки IEnumerable<out T>це коваріант, вам дозволяється робити наступне:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
Другий рядок вище був би невдалим, якби це не було коваріантним, навіть якщо логічно воно повинно працювати, оскільки рядок походить від об'єкта. Перед тим, як до C # і VB.NET (у .NET 4 з VS 2010) додано відхилення в загальних інтерфейсах , це була помилка часу компіляції.
Після .NET 4, IEnumerable<T>був позначений коваріантом, і став IEnumerable<out T>. Оскільки IEnumerable<out T>використовує лише елементи всередині нього і ніколи не додає / не змінює їх, це безпечно трактувати численну колекцію рядків як численну колекцію об'єктів, що означає, що вона є коваріантною .
Це не працює з таким типом IList<T>, оскільки IList<T>має Addметод. Припустимо, це дозволить:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
Ви можете зателефонувати:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
Це, звичайно, не вдасться - тому IList<T>не можна позначати коваріант.
Також є, btw, варіант для in- який використовується такими речами, як інтерфейси порівняння. IComparer<in T>, наприклад, працює протилежно. Ви можете використовувати бетон IComparer<Foo>безпосередньо як підклас IComparer<Bar>if , оскільки інтерфейс є протилежним .BarFooIComparer<in T>
Image, що це абстрактний клас;) Ви можете робити new List<object>() { Image.FromFile("test.jpg") };без проблем, а також можете new List<object>() { new Bitmap("test.jpg") };. Проблема з вашими полягає в тому, що new Image()це заборонено (ви теж не можете цього зробити var img = new Image();)
IList<object>- це химерний приклад, якщо ви хочете, objectщо вам не потрібні дженерики.
Для легкого запам'ятовування використання inта outключових слів (також коваріації та протиріччя) ми можемо зобразити спадщину як обгортання:
String : Object
Bar : Foo

врахуйте,
class Fruit {}
class Banana : Fruit {}
interface ICovariantSkinned<out T> {}
interface ISkinned<T> {}
і функції,
void Peel(ISkinned<Fruit> skinned) { }
void Peel(ICovariantSkinned<Fruit> skinned) { }
Функція, яка приймає ICovariantSkinned<Fruit>, зможе прийняти ICovariantSkinned<Fruit>або ICovariantSkinned<Bananna>тому, що ICovariantSkinned<T>є коваріантним інтерфейсом і Bananaє типом Fruit,
функція, яка приймає ISkinned<Fruit>, зможе прийняти ISkinned<Fruit>.
" out T" означає, що тип T"коваріантний". Це обмежує Tвідображатись лише як повернене (вихідне) значення у методах загального класу, інтерфейсу чи методу. Це означає, що тип / інтерфейс / метод можна привласнити еквіваленту супер-типу T.
Напр. ICovariant<out Dog>Можна подати до ICovariant<Animal>.
outправозастосування, які Tможна повернути, поки я не прочитав цю відповідь. Вся концепція має більше сенсу зараз!
З посилання, яке ви опублікували ....
Для загальних параметрів типу ключове слово out визначає, що параметр типу є коваріантним .
EDIT : Знову від посилання, яке ви опублікували
Для отримання додаткової інформації див. Коваріація та контраваріантність (C # та Visual Basic). http://msdn.microsoft.com/en-us/library/ee207183.aspx