delegates and inheritance

  • Thread starter Thread starter codefragment
  • Start date Start date
C

codefragment

Hi
I just had a bit of a surprise, I expected this to work!

public class A
{
}

public class AChild : A
{
}

public class B
{
}

public class BChild : B
{
}

public delegate A TheDelegate(B b);

private AChild Func(BChild b)
{
return null;
}

public void CallDelegate()
{
TheDelegate a= new TheDelegate(Func);
}


Of course it doesn't work because Func uses child classes of the kinds
used in the
delegate.
Why doesn't this work, if I made a delegate like this:

public delegate object TheDelegate(object b);

I'd expect any function that took any class and returned any class to
work.

However, thats the state of affairs so any way of doing what I want to
do here? i.e. call
Func later?

Ta
C
 
(e-mail address removed) wrote in @g44g2000cwa.googlegroups.com:
public delegate A TheDelegate(B b);

private AChild Func(BChild b)
{
return null;
}

public void CallDelegate()
{
TheDelegate a= new TheDelegate(Func);
}


Of course it doesn't work because Func uses child classes of the kinds
used in the
delegate.
Why doesn't this work, if I made a delegate like this:

public delegate object TheDelegate(object b);

I'd expect any function that took any class and returned any class to
work.

Yeah it would work, if the delegate and the function declaration were the
same... If you change your Func(...) so that it accepts a B and returns an
A then it will work fine, even if it returns an AChild - you'll just have
to cast the result.

-mdb
 
Not an option for me, I've got a hundred or so of these methods.
Wouldn't a C style function pointer have worked in this case?
 
I could have lived with that :-) Nice thing about c++ is that when you
needed to get down and dirty it allowed you to. Of course
it allowed you to screw up as well...
So, no way around this then. I can't change the methods, their in
(effectively) a third party dll. The only way I can think of
doing this is via reflecton at the moment
 
Say you did this:

public class BChild2 : B
{}

And you were allowed to do this:

TheDelegate d = new TheDelegate(Func);

Now, if you did this:

BChild2 b2 = new BChild2();
d(b2);

You would get an exception because BChild2 can not be cast to BChild,
which is what Func expects. You can pass it to the delegate, because it
expects B, but you can't do it the other way around.

In C# 2.0, you can actually do the reverse. Say your function was this:

Func(B b)

Then, you can say:

TheDelegate d = new TheDelegate(Func);

And that would work, because BChild and BChild2 derive from B.

You might also want to consider declaring your delegate as generic, like
this:

public delegate A TheDelegate<T>(T b) where T : B

This way, you can specify T, but it has to derive from B.

Hope this helps.
 
Of course it doesn't work because Func uses child classes of the kinds
used in the
delegate.
Why doesn't this work, if I made a delegate like this:

public delegate object TheDelegate(object b);

I'd expect any function that took any class and returned any class to
work.

The return value "should" work - the parameter "shouldn't", because
someone with an instance of TheDelegate could call it with a parameter
of new object(). If the implementing method is expecting a string, it's
stuffed at that point. However, the reverse "should" work - if the
method only expects an object parameter, it's okay if the delegate is
more specific.

I've put "should" in quotes because this is the behaviour which is
provided by C# 2.0, but not by C# 1.1. It's return value covariance and
parameter contra-variance, and it only works with delegates (not, for
instance, with interfaces).

See http://www.pobox.com/~skeet/csharp/csharp2/delegates.html
It's incomplete, but the bit you're interested in is there.
 
I could have lived with that :-) Nice thing about c++ is that when you
needed to get down and dirty it allowed you to. Of course
it allowed you to screw up as well...
So, no way around this then. I can't change the methods, their in
(effectively) a third party dll. The only way I can think of
doing this is via reflecton at the moment

You could always wrap the real delegate in your own delegate, calling
the real one and casting appropriately. Ugly, but it would work. (If
you're using C# 2.0 it makes things a bit easier for the reasons I
mentioned before.)
 
"Hope this helps"
Well, it probably will do when I get to work on that version so thanks,
reflection for now and templates (I wish), sorry generics later

Active newsgroup this isn't it :-)
 
Back
Top