Cole Johnson Cole Johnson - 11 months ago 38
C# Question

"out T" vs. "T" in Generics

What is the difference between

<out T>
and
<T>
? For example:

public interface IExample<out T>
{
...
}


vs.

public interface IExample<T>
{
...
}





The only info I have gotten from MSDN was that


You can use the out keyword in generic interfaces and delegates.

Answer Source

The out keyword in generics is used to denote that the type T in the interface is covariant. See Covariance and contravariance for details.

The classic example is IEnumerable<out T>. Since IEnumerable<out T> is covariant, you're allowed to do the following:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

The second line above would fail if this wasn't covariant, even though logically it should work, since string derives from object. Before variance in generic interfaces was added to C# and VB.NET (in .NET 4 with VS 2010), this was a compile time error.

After .NET 4, IEnumerable<T> was marked covariant, and became IEnumerable<out T>. Since IEnumerable<out T> only uses the elements within it, and never adds/changes them, it's safe for it to treat an enumerable collection of strings as an enumerable collection of objects, which means it's covariant.

This wouldn't work with a type like IList<T>, since IList<T> has an Add method. Suppose this would be allowed:

IList<string> strings = new List<string>();
IList<object> objects = strings;  // NOTE: Fails at compile time

You could then call:

objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object

This would, of course, fail - so IList<T> can't be marked covariant.

There is also, btw, an option for in - which is used by things like comparison interfaces. IComparer<in T>, for example, works the opposite way. You can use a concrete IComparer<Foo> directly as an IComparer<Bar> if Bar is a subclass of Foo, because the IComparer<in T> interface is contravariant.