
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
65 lines
3.0 KiB
Plaintext
65 lines
3.0 KiB
Plaintext
== Why is this an issue?
|
|
|
|
In the interests of making code as usable as possible, interfaces and delegates with generic parameters should use the ``++out++`` and ``++in++`` modifiers when possible to make the interfaces and delegates covariant and contravariant, respectively.
|
|
|
|
|
|
The ``++out++`` keyword can be used when the type parameter is used only as a return type in the interface or delegate. Doing so makes the parameter covariant, and allows interface and delegate instances created with a sub-type to be used as instances created with a base type. The most notable example of this is ``++IEnumerable<out T>++``, which allows the assignment of an ``++IEnumerable<string>++`` instance to an ``++IEnumerable<object>++`` variable, for instance.
|
|
|
|
|
|
The ``++in++`` keyword can be used when the type parameter is used only as a method parameter in the interface or a parameter in the delegate. Doing so makes the parameter contravariant, and allows interface and delegate instances created with a base type to be used as instances created with a sub-type. I.e. this is the inversion of covariance. The most notable example of this is the ``++Action<in T>++`` delegate, which allows the assignment of an ``++Action<object>++`` instance to a ``++Action<string>++`` variable, for instance.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,csharp]
|
|
----
|
|
interface IConsumer<T> // Noncompliant
|
|
{
|
|
bool Eat(T fruit);
|
|
}
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,csharp]
|
|
----
|
|
interface IConsumer<in T>
|
|
{
|
|
bool Eat(T fruit);
|
|
}
|
|
----
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Add the "[in|out]" keyword to parameter "X" to make it "[covariant|contravariant]".
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== on 8 Jul 2015, 15:17:03 Ann Campbell wrote:
|
|
\[~tamas.vajk] note that the description I've written is for the "me" from last week. If it states too much of what is obvious to C# developers, please let me know what should be eliminated.
|
|
|
|
=== on 20 Jul 2015, 12:20:09 Tamas Vajk wrote:
|
|
\[~ann.campbell.2] I think the description is okay. We could shorten it, but it's not necessary. ``++in++`` and ``++out++`` is not used too often, so it's not necessarily common knowledge.
|
|
|
|
|
|
I've modified the description a bit. ``++IComparer++`` is not the most notable example for ``++in++`` generic arguments. We haven't discussed this, but this rule also applies for delegates with generic parameters. And the most notable example for ``++in++`` is the ``++Action++`` delegate: \https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx
|
|
|
|
|
|
A side note: the most notable example of having both ``++in++`` and ``++out++`` is probably the ``++Func<T, TResult>++`` delegate: \https://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx
|
|
|
|
=== on 20 Jul 2015, 14:09:21 Ann Campbell wrote:
|
|
Thanks [~tamas.vajk]. Note that I've just worked covariant/contravariant into the description in the appropriate places. I suddenly realized we described them but didn't actually attach the descriptions to the words!
|
|
|
|
endif::env-github,rspecator-view[]
|