contravariance seem to cause a conflicted behavior - c#

The following example is taken from C# in Depth: What you need to master C# 2 and 3, and seems to only only cause a breaking change as jskeet has identified, but be wrong. Please explain:
delegate void SampleDelegate(string x);
public void CandidateAction (string x)
{
Console.WriteLine("Snippet.CandidateAction")
}
public class Derived: Snippet
{
public void CandidateAction (object x)
{
Console.WriteLine("Derived.CandidateAction")
}
}
....
Derived x = new Derived();
SampleDelegate factory = new SampleDelegate (x.CandidateAction);
factory ("test");
Now, why should it work altogether as SampleDelegate accept string not the object. And to my knowledge, object doesn't derive from the string. It is the other way around. That's what contravariance permits under c# 2.0. The seems to demonstrate the opposite effect.

Conceptually, Derived.CandidateAction's signature is saying, "I can handle any object you want to throw at me." SampleDelegate's contract is "You have to be able to handle a string." Now if a method can handle any object, it can certainly handle a string. So Derived.CandidateAction is capable of fulfilling what SampleDelegate needs, and can therefore be assigned to a SampleDelegate variable.
I wrote a more detailed discussion of this (admittedly from a C# 4 point of view) at http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html.

Contravariance allows you to use a method which has parameters which are a base type of the parameters in the delegate method signature.
The delegate signature defines what types will be passed to the method. The method itself can have types that are less "specific". In your example, when the delegate is invoked as string is being passed. It is perfectly ok for the actual method to only want an object because a variable of type object is allowed to hold an instance of type string.
This is most useful in event handling scenarios where you can write an event handler like this that can be attached to almost any event (even when the args parameter being passed is more specific like ItemCheckedEventArgs):
public void GenericHandler(object source, EventArgs args) {
//do something generic
}

Related

Covariance in delegate, any example?

I'm reading this msdn article, the contravariance example (keyboard and mouse event) is great and useful, while the covariance example (Mammal and Dog) doesn't look so.
The keyboard and mouse event is great since you can use 1 handler for multiple cases; but I can't think of the advantages of assigning a handler that returns a more derived type to a handler returning base type, not to mention it looks like less common to have a delegate which cares about return type?
Could someone please provide a more practical example of covariance in delegate?
Here's a "real world" example where I implement a service locator. I want to make a class where I can register "factory" delegates that know how to produce instances of some type, then resolve instances of some type later on. Here is what that looks like:
interface ISomeService { ... }
class SomeService : ISomeService { ... }
class IocContainer
{
private readonly Dictionary<Type, Func<object>> _factories = new Dictionary<Type, Func<object>>();
public void Register<T>(Func<T> factory)
where T: class
{
_factories[typeof(T)] = factory;
}
// Note: this is C#6, refactor if not using VS2015
public T Resolve<T>() => (T)_factories[typeof(T)]();
}
class Program
{
static void Main(string[] args)
{
var container = new IocContainer();
container.Register<ISomeService>(() => new SomeService());
// ...
var service = container.Resolve<ISomeService>();
}
}
Now, where I'm doing container.Register<ISomeService>(() => new SomeService()), the covariance of Func delegates comes into play on two levels:
I can pass in a Func<SomeService> and it is assignable where a Func<ISomeService> is expected with no problems, because a SomeService is a ISomeService
Inside the Register method, a Func<T> can be assigned where a Func<object> is expected with no problems, because any reference type is an object
If a Func<SomeService> wasn't assignable to a Func<ISomeService>, or Func<ISomeService> wasn't assignable to a Func<object> (via covariance), this example wouldn't work.
You are right, it is not common an event to return with a value, it's kinda convention (actually it is more than convention: see extra reading #2). However delegates are not only for events, basically they are the .NET version of the near half century old C style "pointer to a function" (C terminology).
To leave the mystery left on events and delegates and listeners (java) in control flow concept they are just simple callbacks, so it is completely reasonable if they have return value.
So from this callback point of view:
Say I would like to process animals. I would like to use a function pointer (I mean: delegate or lambda) to do a part of this processing. Lets call it FeedAnimal. I would like to have an other skeleton method which calls this feed method, lets call it CareAnimal. I would like to plugin the feed algorithm to the care algorithm with run time variable mode, so the Care will have a delegate parameter: feed. After feeding the feed method returns an animal.
Now the point: The feed will have different implementations for Dog and Cat, one returns with Dog and the other returns with Cat.... and the Care() method accepts a delegate parameter which returns with Animal.
[Extra reading #1]: This kind of polymorphic implementation is the not OOP polymorphism implementaion. In OOP you can achieve similar with virtual method overloads.
[Extra reading #2]: The really disturbing thing about delegates (and events) that they are multicast delegates I mean one single delegate (which is a multicast delegate by default) can contain many method entry point. When it is invoked then all contained methods invoked in a cycle in not specified order. However there will be one return value in case the signature is not void. Of course this is confusing, so we safely say: If we use the multicast feature of delegates (or events) then it makes no sense other signature than void return.
Events are typically multicast, this comes from the Publisher/Subscriber DP metaphore: Many subscriber (handler) can subscribe (+=) to the publishers publication without knowing anything about each other.
Well, if you look at the declaration of the Func<T, TResult> Delegate.
public delegate TResult Func<in T, out TResult>(
T arg
)
You can see that the type of the input parameter is contravariant but the type of the result or return value is covariant.
The familiar Linq extension Select, has an overload that accepts this delegate.
Additionally, note that the return type of Select is IEnumerable<T>,
that is a covariant interface, i.e.
public IEnumerable<out T>
{
\\ ...
}
Now consider the types,
abstract class Mammal
{
}
and
class Dog : Mammal
{
}
I can declare an instance of the delegate.
var doItToMammals = new Func<Mammal, Mammal>(mammal => mammal);
I can pass this delegate to Select without variance.
IEnumerable<Mammal> mammals = new List<Mammal>().Select(doItToMammals);
Now, because the input of the function is contravariant, I can do
IEnumerable<Mammal> mammals = new List<Dog>().Select(doItToMammals);
Now here's the point, because the result is covariant, I can do
IEnumerable<Dogs> dogs = new List<Dog>().Select<Dog, Dog>(doItToMammals);

Delegate Questions

I am new to C# and have two questions about delegates.
MSDN shows that the Delegate class only has two constructors, both which take two arguments each. However, in the program below, I am instantiating a Delegate object with a seemingly one-parameter constructor (see the commented line).
using System;
static class Program
{
public delegate void MyDelegate();
static void MyMethod()
{
Console.WriteLine("I'm inside MyMethod!");
}
static void Main()
{
MyDelegate myDelegate = new MyDelegate(MyMethod); // Constructor Call
myDelegate();
}
}
Am I misunderstanding something?
My second question is: when declaring delegates with one or more parameters, why do we need to give the parameters names? In C++, we could do something like this inside classes:
public delegate void MyOtherDelegate(int, int, string);
It may look like you're calling a standard constructor, but the C# compiler is actually doing a little slight of hand with your code. When you write
MyDelegate myDelegate = new MyDelegate(MyMethod);
You're not actually invoking any of the constructors listed on MSDN directly. It instead calls a constructor that the compiler has automatically defined on the delegate type MyDelegate (these constructors are not shown on MSDN). In fact, the constructors that are listed on MSDN cannot even be called directly:
This constructor cannot be used in application code. To create a delegate by specifying the name of an instance method, use an overload of the CreateDelegate method…
It's worth noting that you can even do this for brevity:
MyDelegate myDelegate = MyMethod;
As for why parameter names are necessary, perhaps they may not be strictly necessary for compilation in general, but I suspect that the designers of the CLR wanted to be consistent with other features of the in the run-time. It allows you to do things like specifying explicit parameter names that you wouldn't be able to do otherwise:
Func<int, int> foo = x => x + 1;
foo(arg: 1);
It also means you can inspect the parameter names through reflection and potentially do some useful processing with them.
Not exactly answering your question but just so you are aware, C# also supports Func delegates. in which case you don't need to even declare anything.
e.g. This method accepts a delegate with a parameter of type string and output of Int
public static void DoSomethingWithDelegate(Func<string, Int32> converstionDelegate)
{
int x = converstionDelegate("1");
}
Read more about it here: http://msdn.microsoft.com/en-us/library/bb549151.aspx

How to delegate correct Action<Interface>?

I'm a beginner with C# and can't find any answer for this :
Im trying to delegate Actions with some interface parameter , but push through functions with objects that extend this interface (or class)
// some class extending interface
public class IntEvent : IFace{}
public class MoveEvent : IFace{}
// function i like to use to verify Action
static void setAction(Action<IFace> evt) {
// evt ...
}
// function to delegate as Action
static void evtCheck(IntEvent evt) {
// some func
}
static void evtMove(MoveEvent evt) {
// some func
}
// class {
// call method inside class and delegate this function :
setAction(evtCheck);
setAction(evtMove);
I'm receiving an error that "evtCheck(IntEvent) cannot be converted to Action<IFace>" , even if IntEvent extends the IFace interface .
How should I solve this ? Maybe I have to use Func or Delegate ?
You can't do what you're trying to do - you're expecting covariance, but Action<T> is contravariant on its only type-parameter.
You can't do a method-group conversion from evtCheck to Action<IFace> because evtCheck needs a more specific type (IntEvent) as its argument than the more general IFace type that an Action<IFace> instance expects. If such a conversion were allowed, what would you expect to happen if the delegate were executed with an argument that implements IFace but is not an IntEvent?
I think you should have another look at your design because it looks like there's a flaw there, but if you want, you can create a lambda to force a cast of the argument to the desired type and accept the possibility of an InvalidCastException:
setAction(iFace => evtCheck((IntEvent)iface));
More likely, you might want to make evtCheck accept a more general type or setAction to accept a more specific delegate.
Action<T> is contravariant in T, so methods taking an Action<T> will also accept Action<U> where T is derived from U.
Your IntEvent class, however, implements the IFace interface, which means that if the compiler accepted your setAction() call, it would be possible to call evtCheck() with an argument that is another IFace-derivative and not IntEvent, a runtime error and a clear violation of type safety.
Obligatory Eric Lippert reference: Covariance and contravariance
EDIT: from your description it seems to me that what you really want is differentiation based on the method parameter's type, so e.g. you want a separate action for IntEvent, another one for (a hypothetical) DoubleEvent etc. If this is the case, you are actually after double virtual dispatch, which is not directly supported in C#, but you can simulate it using the Visitor design pattern.

C# function that takes pointer to function as an in parameter without declaring any specific delegate types?

I want to implement a method that will find stuff in my custom class. It should work like generic collections work - i pass a pointer to a function, and the method will iterate through all it has to look in, apply this function, and if it returns true return the found item.
I'd like to pass function pointer as a parameter, but i dont want to declare delegate types.
I know i can do something like:
delegate bool Foo(MyClass)
MyClass MyMethod(Foo x)
{...}
And i know i can do something like this:
MyClass MyMethod(Func<MyClass,bool> x)
But can i do it without declaring a delegate type and without using built in stuff like Func<> which has limits on how many parameters i can have (in case of Func, one...)
You can just use delegate if you want, although it's a bit old school :)
public void TestInvokeDelegate()
{
InvokeDelegate( new TestDelegate(ShowMessage), "hello" );
}
public void InvokeDelegate(TestDelegate del, string message)
{
del(message);
}
public delegate void TestDelegate(string message);
public void ShowMessage(string message)
{
Debug.WriteLine(message);
}
You can allways pass in a Delegate and call DynamicInvoke on it:
MyClass MyMethod(Delegate x) {
// ...
x.DynamicInvoke(....);
// ...
}
It looks like you are trying to implement the Visitor pattern. In this case visiting methods usually have only one parameter - the instance to visit. Having additional arguments passed around conceals the use of the pattern and makes it harder to reason about. This article shows you one way to implement it in C#.
The key is to create a visitor class that will encapsulate all the parameters that affect the visiting process. This way you don't need to pass anythnig other than an object in question in the visiting method - everything else lives in instance fields.
However, if you really want to pass some additional parameters in the method and don't know what type they can have, there are ways to do that. More or less standard approach in .NET world is to use a delegate without return value and with single parameter of type object, the example would be ParameterizedThreadStart delegate:
public delegate void ParameterizedThreadStart(
Object obj
)
This way you get to pass only one parameter in the delegate, but it could be anything - an instance of a class, an array or null, if you end up not needing additional arguments after all. The downside of this approach is that it requires type casting which can lead to runtime errors.

How are method overloads selected when types are not known at compile time?

Say I have the following code:
public class SomeClass
{
// Other stuff...
public void ApplyEvent<T>(IPublishedEvent<T> evt)
{
Handle(evt.Payload);
}
protected virtual void Handle(ThingyCreatedEvent evt)
{
Code = evt.Code;
Label = evt.Label;
}
protected virtual void Handle<T>(T evt)
{
throw new NotImplementedException(
String.Format("Not set to handle {0}", evt.GetType().FullName));
}
}
evt.Payload is of type T. My hope was to be able to handle methods for specific event types I expect, and have a catch-all method that will throw if an unexpected event type is provided for some reason.
What I've found, though, is that the generic method gets called even if T is of type ThingyCreatedEvent, unless I explicitly cast it:
Handle(evt.Payload as ThingyCreatedEvent);
I get the same results if, instead of a generic Handle method, I define a Handle method with an Object type parameter.
Can anyone explain this? I'd like to have a better understanding of what's going on here. I would have expected it to dispatch according to the actual type provided at run-time.
Generics are resolved at compile-time - the compiler needs to know what is the type of T. If you're looking to use a type that is going to be resolved at runtime, you should look up the keyword "dynamic".
All the code - including overload resolution - is compiled once, at normal compilation time, and the overload decisions have to be made without any knowledge of what T is unless there are constraints on it. The method call Handle(evt.Payload); is resolved once with only the knowledge that the type of evt.Payload is T, so it has to resolve to Handle<T>(T evt).
If you really want overload resolution at execution time, and if you're using C# 4, you can use dynamic typing:
public void ApplyEvent<T>(IPublishedEvent<T> evt)
{
dynamic payload = evt.Payload;
Handle(payload);
}

Categories