out T vs T in Generics
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.
what is in T and out T in Generics
<out T>
denotes that T
is covariant.
It seems plausible that a sequence of giraffes can be treated as a sequence of animals. "Covariance" of an interface means that "if there is an implicit reference conversion from Giraffe
to Animal
then there is also an implicit reference conversion from I<Giraffe>
to I<Animal>
. The convertibility of the constructed type "varies in the same direction" as the convertibility of the type arguments.
Example:
// Valid! // Invalid!
// Every giraffe is an animal // Not every animal is a giraffe
IEnumerable<Giraffe> giraffes = ...; IEnumerable<Animal> animals = ...;
IEnumerable<Animal> animals = giraffe; IEnumerable<Giraffe> giraffes = animals;
Animal animal = animals.First(); Giraffe giraffe = giraffes.First();
<in T>
denotes that T
is contravariant.
It seems plausible that code which can compare two animals can also compare two giraffes. "Contravariance" of an interface is the same as covariance with the direction reversed. It means that "if there is an implicit reference conversion from Giraffe
to Animal
then there is also an implicit reference conversion from I<Animal>
to I<Giraffe>
. The convertibility of the constructed type "varies in the opposite direction" as the convertibility of the type arguments.
Example:
// Valid! // Invalid!
// Animal comparer can compare // Giraffe comparer cannot compare
// giraffes // arbitrary animals
IComparer<Animal> animalC = ...; IComparer<Giraffe> giraffeC = ...;
IComparer<Giraffe> giraffeC = animalC; IComparer<Animal> animalC = giraffeC;
int result = giraffeC.Compare(x, y); int result = animalC.Compare(x, y);
See:
- Covariance and Contravariance (C# and Visual Basic)
- Variance in Generic Interfaces (C# and Visual Basic)
- out (Generic Modifier) (C# Reference)
- in (Generic Modifier) (C# Reference)
Is it possible to use the generic in and out modifier on the same T?
One could have interfaces IReadable<out T> { T read(int index); }
, IWritable<in T> { void write(int index, T dat);
, ISplitReadWrite<out Tout, in Tin>:IReadable<Tout>,IWritable<Tin>
, and IReadWrite<T>:ISplitReadWrite<T,T>
.
If one has a class MyCollection<T>
which implements IReadWrite<T>
, then a MyCollection<Cat>
could be converted to IReadable<Animal>
, IWritable<SiameseCat>
, or an ISplitReadWrite<Animal,SiameseCat>
. Note, however, that the only IReadable<T>
that would yield an item that could be stored into a MyCollection<Cat>
would be IReadable<Cat>
, the only IWritable<T>
that could handle everything that might appear in a MyCollection<Cat>
would be IWritable<Cat>
. The only forms of ISplitReadWrite<Tout,Tin>
that would allow one to read out an item and write it back to the same collection without a cast would be those where the two types were the same, and the only such type implemented by MyCollection<Cat>
would be ISplitReadWrite<Cat,Cat>
.
Note that one could have an interface with methods that could be equally usable with MyCollection<Animal>
and MyCollection<SiameseCat>
, such as "swap the items in slots i1 and i2 of the same collection", but such an interface wouldn't need any generic parameter at all. Id one has an IPermutable
interface, it could include methods like void swapItems(int i1, int i2);
which wouldn't have any generic types in their signatures, and thus wouldn't make it necessary for the type to include any generic type arguments.
What does out mean before a Generic type parameter?
It is one of the two generic modifiers introduces in C# 4.0 (Visual Studio 2010).
It signifies that the generic parameter it is declared on is covariant.
The in
modifier signifies the generic parameter it is declared on is contravariant.
See out (Generic Modifier) and in (Generic Modifier) on MSDN.
Typescript generic type parameters: T vs T extends {}
Note: I'll assume you're using a version of TypeScript 3.5 or later; in TypeScript 3.5 a change was made so that generic type parameters are implicitly constrained by unknown
instead of the empty object type {}
, and some minor details about the difference between funcA()
and funcB()
changed. I don't want to make a long post even longer by talking about how things used to be in TS3.4 and below.
If you don't explicitly constrain a generic type parameter via extends XXX
, then it will implicitly be constrained by unknown
, the "top type" to which all types are assignable. So in practice that means the T
in funcA<T>()
could be absolutely any type you want.
On the other hand, the empty object type {}
, is a type to which nearly all types are assignable, except for null
and undefined
, when you have enabled the --strictNullChecks
compiler option (which you should). Even primitive types like string
and number
are assignable to {}
.
So compare:
function funcA<T>() { }
funcA<undefined>(); // okay
funcA<null>(); // okay
funcA<string>(); // okay
funcA<{ a: string }>(); // okay
with
function funcB<T extends {}>() { }
funcB<undefined>(); // error
funcB<null>(); // error
funcB<string>(); // okay
funcB<{ a: string }>(); // okay
The only difference is that T extends {}
forbids null
and undefined
.
It might be a little confusing that {}
, a so-called "object" type, would accept primitives like string
and number
. It helps to think of such curly-brace-surrounded types like {}
and {a: string}
as well as all interface
types not necessarily as "true" object types, but as types of values where you can index into them as if they were objects without getting runtime errors. Primitives except for null
and undefined
are "object-like" in that you can treat them as if they were wrapped with their object equivalents:
const s: string = "";
s.toUpperCase(); // okay
And therefore even primitives like string
are assignable to curly-brace-surrounded types as long as the members of those types match:
const x: { length: number } = s; // okay
If you really need to express a type that only accepts "true", i.e., non-primitive objects, you can use the object
:
const y: object & { length: number } = s; // error
const z: object & { length: number } = { length: 10 }; // okay
But I (seriously) digress.
Okay, hope that helps; good luck!
Playground link to code
What is the difference between 'E', 'T', and '?' for Java generics?
Well there's no difference between the first two - they're just using different names for the type parameter (E
or T
).
The third isn't a valid declaration - ?
is used as a wildcard which is used when providing a type argument, e.g. List<?> foo = ...
means that foo
refers to a list of some type, but we don't know what.
All of this is generics, which is a pretty huge topic. You may wish to learn about it through the following resources, although there are more available of course:
- Java Tutorial on Generics
- Language guide to generics
- Generics in the Java programming language
- Angelika Langer's Java Generics FAQ (massive and comprehensive; more for reference though)
Java Generics WildCard: ? extends Number vs T extends Number
There is no difference in this case, because T
is never used again.
The reason for declaring a T
is so that you can refer to it again, thus binding two parameter types, or a return type together.
What is out keyword in kotlin
With this signature:
List<out T>
you can do this:
val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList
which means T is covariant:
when a type parameter T of a class C is declared out, C<Base> can safely be a supertype of C<Derived>.
This is contrast with in, e.g.
Comparable<in T>
you can do this:
fun foo(numberComparable: Comparable<Number>) {
val doubleComparable: Comparable<Double> = numberComparable
// ...
}
which means T is contravariant:
when a type parameter T of a class C is declared in, C<Derived> can safely be a supertype of C<Base>.
Another way to remember it:
Consumer in, Producer out.
see Kotlin Generics Variance
-----------------updated on 4 Jan 2019-----------------
For the "Consumer in, Producer out", we only read from Producer - call method to get result of type T; and only write to Consumer - call method by passing in parameter of type T.
In the example for List<out T>
, it is obvious that we can do this:
val n1: Number = numberList[0]
val n2: Number = doubleList[0]
So it is safe to provide List<Double>
when List<Number>
is expected, hence List<Number>
is super type of List<Double>
, but not vice versa.
In the example for Comparable<in T>
:
val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)
So it is safe to provide Comparable<Number>
when Comparable<Double>
is expected, hence Comparable<Double>
is super type of Comparable<Number>
, but not vice versa.
Difference between ? super T and ? extends T in Java
extends
The wildcard declaration of List<? extends Number> foo3
means that any of these are legal assignments:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
Reading - Given the above possible assignments, what type of object are you guaranteed to read from
List foo3
:- You can read a
Number
because any of the lists that could be assigned tofoo3
contain aNumber
or a subclass ofNumber
. - You can't read an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't read a
Double
becausefoo3
could be pointing at aList<Integer>
.
- You can read a
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can't add an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't add a
Double
becausefoo3
could be pointing at aList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aList<Integer>
.
- You can't add an
You can't add any object to List<? extends T>
because you can't guarantee what kind of List
it is really pointing to, so you can't guarantee that the object is allowed in that List
. The only "guarantee" is that you can only read from it and you'll get a T
or subclass of T
.
super
Now consider List <? super T>
.
The wildcard declaration of List<? super Integer> foo3
means that any of these are legal assignments:
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from
List foo3
:- You aren't guaranteed an
Integer
becausefoo3
could be pointing at aList<Number>
orList<Object>
. - You aren't guaranteed a
Number
becausefoo3
could be pointing at aList<Object>
. - The only guarantee is that you will get an instance of an
Object
or subclass ofObject
(but you don't know what subclass).
- You aren't guaranteed an
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can add an
Integer
because anInteger
is allowed in any of above lists. - You can add an instance of a subclass of
Integer
because an instance of a subclass ofInteger
is allowed in any of the above lists. - You can't add a
Double
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add an
Object
becausefoo3
could be pointing at anArrayList<Integer>
.
- You can add an
PECS
Remember PECS: "Producer Extends, Consumer Super".
"Producer Extends" - If you need a
List
to produceT
values (you want to readT
s from the list), you need to declare it with? extends T
, e.g.List<? extends Integer>
. But you cannot add to this list."Consumer Super" - If you need a
List
to consumeT
values (you want to writeT
s into the list), you need to declare it with? super T
, e.g.List<? super Integer>
. But there are no guarantees what type of object you may read from this list.If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g.
List<Integer>
.
Example
Note this example from the Java Generics FAQ. Note how the source list src
(the producing list) uses extends
, and the destination list dest
(the consuming list) uses super
:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
Also see
How can I add to List<? extends Number> data structures?
Related Topics
Comparing Two Strings, Ignoring Case in C#
How to Determine If a Type Implements a Specific Generic Interface Type
Why Should I Implement Icloneable in C#
How to Display a Popup from a Webbrowser in Another Window I Created
SQL Express Connection String: Mdf File Location Relative to Application Location
Adding Items to a List<> of Objects Results in Duplicate Objects When Using a New in a Loop
Parse a Number from Exponential Notation
Why Use Icollection and Not Ienumerable or List<T> on Many-Many/One-Many Relationships
Garbage Collector and Circular Reference
Parallel.Foreach VS Task.Run and Task.Whenall
.Net Events for Process Executable Start
How to Get a Path to the Desktop for Current User in C#
Stopwatch VS. Using System.Datetime.Now for Timing Events
Observeon and Subscribeon - Where the Work Is Being Done
Example Ajax Call Back to an ASP.NET Core Razor Page
"Self Referencing Loop Detected" Exception with JSON.Net
Why Does the Default Parameterless Constructor Go Away When You Create One with Parameters
Windows Application Startup Error Exception Code: 0Xe0434352