RichardHowells
RichardHowells

Reputation: 9096

What does the 'in' mean in public delegate int Comparison<in T>

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

Answers (4)

supercat
supercat

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

Maciej
Maciej

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

Kendall Frey
Kendall Frey

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

NominSim
NominSim

Reputation: 8511

If you are familiar with the docs, why not use them?

It specifies the parameter as a contravariant.

Upvotes: 2

Related Questions