Reputation: 9096
The msdn docs (http://msdn.microsoft.com/en-us/library/tfakywbh.aspx) report the syntax for the Comparison delgate with what looks like a keyword 'in'.
public delegate int Comparison<in T>(
T x,
T y
)
Does the 'in' have any actual meaning? Are there other keywords that may appear there?
Upvotes: 1
Views: 137
Reputation: 81247
Applying the "in" declaration to the type parameter means that the compiler will allow a routine which expects a delegate that would take a derived-type object will be happy if it is given a delegate that accepts a base type object. For example, a routine that expects a delegate to process Zebras will, from a compile-time perspective, be perfectly happy if given a delegate which can process all Animals.
An important thing to note, however, is that because of the unfortunate way MulticastDelegate
and Delegate.Combine
are implemented, attempting to use covariant delegates with any code that will attempt to Delegate.Combine
may cause a crash at run-time, since Delegate.Combine
requires two delegates that are the precise same type. It would be nice if there were a generic method to combine delegates of different types (the method itself would have to be given a type which could be satisfied by both delegates), though the product of such combination couldn't be a MulticastDelegate
(since instances of that class only hold type information for one delegate type). As yet, however, no such method exists.
Upvotes: 0
Reputation: 7961
This delegate is contravariant and in
keyword means that T
is used as an input type only. What contravariance means is that with this delegate type defined:
public delegate int Comparison<in T>(T x, T y);
you would be able to do this:
Comparison<Control> comp1 = (a, b) => (a.Width*a.Height - b.Width*b.Height);
Comparison<TextBox> comp2 = comp1;
Without in
keyword it would complain about the second line saying it can't convert one type into another. But because we know that T
is only used for input it should be legal to assign a delegate that deals with Control
to a delegate pointer that is expected to provide (input) TextBox
. After all TextBox
would fit into Control
.
On the other hand there is covariance. It also relies on types fitting into other types but this time it's for results (in this case result of a delegate).
Covariance and contravariance known collectively as variance does not apply only to generic delegates but also to generic classes and interfaces. Variance also works for non generic delegates and arrays but in an implicit way so no special keywords are required - it just works.
Variance is not an easy subject and I can't compare my explanation to Eric Lippert's series of blog articles. Although it's from 2007 and he talks there about .NET4 C# in future tense it is still a very good read.
Upvotes: 1
Reputation: 44374
in
means the generic parameter is contravariant. This means, in this case, that you can assign a Comparison<Base>
to a Comparison<Derived>
.
You can do this, because a Comparison<Derived>
variable can accept a method which takes Base
type parameters. When you call a Comparison<Derived>
, you need to pass Derived
variables, which happen to be valid parameters to a method accepting Base
parameters. This means that it makes sense to assign a Comparison<Base>
to a Comparison<Derived>
.
The opposite of in
is (naturally) out
. This means the parameter is covariant, and can assign a Derived
generic to a Base
generic. This would be used, for example, in specifying the return type of a delegate.
A handy way of remembering which is which:
in
should only be used for types that are only passed in. out
should only be used for types that are only passed out.
Read more here:
in (Generic Modifier) (C# Reference)
Covariance and Contravariance (C# and Visual Basic)
Upvotes: 5
Reputation: 8511
If you are familiar with the docs, why not use them?
It specifies the parameter as a contravariant.
Upvotes: 2