2013-06-20 17 views
12

W języku C# wszystkie typy delegatów są ze sobą niezgodne, nawet jeśli mają ten sam podpis. Na przykład:Dlaczego wszystkie typy Delegatów są ze sobą niezgodne?

delegate void D1(); 
delegate void D2(); 

D1 d1 = MethodGroup; 
D2 d2 = d1;       // compile time error 
D2 d2 = new D2 (d1);     // you need to do this instead 

Jaki jest powód tej decyzji dotyczącej projektowania zachowania i języka.

+2

Nie mogę podać ci uzasadnienia, ale delegaci byli oryginalną funkcją językową. Od tego czasu dodali metody lambda: [Actions] (http://msdn.microsoft.com/en-us/library/system.action.aspx) i [Funcs] (http://msdn.microsoft.com/ en-us/library/bb534960.aspx), które nie cierpią z powodu tego samego problemu. – Brandon

+0

@brandon Co? Lambdas są konwertowane na delegatów (lub drzewek wyrażeń), a 'Action's i' Func's * to * tylko typy delegatów, więc stosują dokładnie te same reguły. – svick

+0

Delegowane wywołania są również sprawdzane w czasie wykonywania. To było zoptymalizowane, ważny rodzaj optymalizacji, obsługiwana jest tylko ścisła tożsamość typu. To szybko. –

Odpowiedz

23

In C# all delegate types are incompatible with one another, even if they have the same signature. What is the reasoning behind this behaviour and language design decision?

Po pierwsze, myślę, że to sprawiedliwe, by powiedzieć, że wielu projektantów uruchomieniowych i językowych żałować tej decyzji. Pisanie strukturalne na delegatach - czyli dopasowywanie przez podpis - jest często żądaną funkcją i wydaje się dziwne, że Func<int, bool> i Predicate<int> nie mogą być swobodnie przypisywane sobie nawzajem.

Rozumowanie decyzji, tak jak ją rozumiem - i spieszę dodać, że decyzja ta została podjęta około sześć lat przed rozpoczęciem pracy w zespole C# - jest to, że oczekiwano, że będą delegowane typy z semantyka. Chcesz to być błąd typ:

AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; }; 
PureFunction<int, int> pf = af; 

funkcja A „czysta” jest funkcją, która produkuje i konsumuje żadnych skutków ubocznych, zużywa żadnej informacji poza jego argumenty i zwraca stałą wartość, gdy biorąc pod uwagę te same argumenty . Najwyraźniej af zawodzi co najmniej dwa z nich, a więc nie należy go przypisywać do pf jako niejawnej konwersji.

Ale typy delegatów z semantyką nigdy się nie zdarzały, więc teraz jest to trochę nieporozumienie.

+1

Będę musiał zapamiętać ten termin, "* misfeature *". –

+1

Będę pamiętać z sentymentem, że w krótkim czasie uzyskałem więcej głosów niż Eric Lippert. –

15

Zasadniczo, ponieważ kompilator tworzy dla ciebie dwie klasy. Z tego samego powodu nie można zrobić:

class A {} 
class B {} 

void Main() 
{ 
    A a = new A(); 
    B b = a; 
} 

Na przykład, następujący kod

void Main() {} 

delegate void D(); 
class C {} 

kod IL jest:

D.Invoke: 

D.BeginInvoke: 

D.EndInvoke: 

D..ctor: 

C..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   
2

Delegat to nic innego jak tylko kolejny rodzaj. Są one niezgodne z tego samego powodu, ponieważ class A {} i class B {} byłyby niezgodne.

delegate void D1(); 

Will około skompilować coś jak:

class D1 : MulticastDelegate { .... } 
Powiązane problemy