Does delegate not accept subclass?

My delegate does not seem to accept the subclass, I think the example is the simplest.

public class A
{
     public A() { }
}

public class B : A
{
     public B() { }
}

public class Program
{
     private delegate void CallBack(A a);
     private static CallBack callBack = new CallBack(Test);

     public Main(string[] args)
     {
          callBack(new B());
     }

     private static void Test(A a)
     {
          Console.WriteLine("Test()");    
     }

     // Compilation error occurs if Test becomes:
     private static void Test(B a)
     {
          Console.WriteLine("Test()");
     }
 }

When I change Test to accept B, it throws a compilation error. Is it odd because Bextends A?

Compiler Error :

No overload for test matches. Callback

Is there a way to get my delegate to accept a class that extends A?

+5
source share
4 answers

, C, A, Test(), B. , Callback, A, . Callback, B, Test() B.

class C : A {};

Callback callback = Test;

callback(new C()); //what if Test() accepted B???
+3

, B A?

, . , :

class Animal {}
class Reptile : Animal {}
class Snake : Reptile {}
class Mammal : Animal {}
class Tiger : Mammal {}
class Giraffe : Mammal {}
delegate void D(Mammal m);
static void DoAnimal(Animal a) {}
static void DoMammal(Mammal m) {}
static void DoTiger(Tiger t) {}

D dm = DoMammal;
dm(new Tiger());

. dm , , .

D dt = DoTiger;
dt(new Giraffe());

. , , , , , , . , , .

?

D da = DoAnimal;
da(new Giraffe());

. da , . , , , . DoAnimal (Animal) D (Mammal), Mammal Animal. , ?

, , :

delegate Mammal F();
static Animal GetAnimal() {...}
static Mammal GetMammal() {...}
static Tiger GetTiger() {...}

F fm = GetMammal; 
Mammal m = fm();

.

F ft = GetTiger;
Mammal t = ft();

; GetTiger , , , .

F fa = GetAnimal;
Mammal a = fa();

. GetAnimal Snake, , Mammal, Snake. .

" ", # 2.0. . :

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx

+8

. :

class A { }
class B : A { }

1

public delegate void CallBack(A a);
public void Test(A a) { }
CallBack cb = new CallBack(Test);
cb(new A()); //good and easy usage

2 CallBack(A a) Test(B b)

//compile error, because Test(B b) has a smaller argument scope than CallBack
//CallBack cb = new CallBack(Test);

3 CallBack(B b) Test(A a)

CallBack cb = new CallBack(Test);
cb(new A());  //no error, becasue B can convert to A
+1

C # delegates support covariance and contravariance , so this should work.

The problem is overload.

 // this delegate supports contravariance - and subclass of A should work
 delegate void CallBack(A a);

 // however this can't pick up either Test because both could be used
 static CallBack callBack = new CallBack(Test);

Which signature of the overload method ( Test(A a)or Test(B b)) should be allowed at compile time, but both can be applied, so an error occurs.

You can avoid this by splitting the overload:

 static void TestA(A a)
 {
      Console.WriteLine("Test(a)");    
 }

 // Compilation error occurs if Test becomes:
 static void TestB(B a)
 {
      Console.WriteLine("Test(b)");
 }

 // this is valid because it an exact match
 static CallBack callBackA = new CallBack(TestA);

 // this is valid because delegates support contravariance 
 static CallBack callBackB = new CallBack(TestB);

In any case, you can pass B:

// B is subclass of A, so can be passed to TestA
callBackA(new B());

// CallBack supports contravariance, so can call TestB
callBackB(new B());

Given that you have this contravariance, why do you need overload?

-1
source

All Articles