W pierwszej próbce jest obsada właśnie zrobiona pod kołdrą?
Tak, możesz tak powiedzieć!
Metoda Combine
została napisana w .NET 1, gdzie nie istniał ogólny C#. Dlatego formalny typ powrót Combine
musiał być Delegate
:
public static Delegate Combine(Delegate a, Delegate b)
{
...
}
Jednak metoda nadal zwraca Action
gdy zarówno a
i b
są Action
. I tak, a
i b
są wymagane do tego samego typu środowiska wykonawczego.
Nie pisz MulticastDelegate.Combine
jako Combine
jest metodą static
zdefiniowaną przez klasę System.Delegate
. Dlatego powiedzmy: Delegate.Combine
, to mniej mylące.
Objazd:
Aktualna wersja C# i Combine
ma problemy z kontrawariantny typów delegatów. Rozważmy następujący:
Action<string> doSomethingToString; // will be assigned below
Action<ICloneable> a = cloneable => { Console.WriteLine("I'm cloning"); cloneable.Clone(); }
Action<IConvertible> b = convertible => { Console.WriteLine("I'm converting"); convertible.ToInt32(CultureInfo.InvariantCulture); }
Action<string> aStr = a; // OK by contravariance of Action<in T>, aStr and a reference same object
Action<string> bStr = b; // OK by contravariance of Action<in T>, bStr and b reference same object
doSomethingToString = aStr + bStr; // throws exception
doSomethingToString("42"); // should first clone "42" then convert "42" to Int32
Teraz załóżmy, że jakiś przyszły wersja ramach wprowadziła ogólny Combine
metody:
public static TDel Combine<TDel>(TDel a, TDel b) where TDel : Delegate
{
// use typeof(TDel) to figure out type of new "sum" delegate
}
i załóżmy C# został zmieniony w taki sposób, +
został przetłumaczony na wywołanie nowy generic Combine<>
metoda, a następnie połączenie kontrawariancji i delegacji zostanie naprawione! Sądzę, że mówią nam, że mają wyższe priorytety, ale wciąż.
Czy istnieje jakikolwiek problem z podstawowym każdy typ delegata definiuje własną metodę statyczną 'Combine'? Następnie, jeśli dwóch delegatów "X" i "Y" było obu typów, które można podstawić do 'FooDelegate', można użyć' FooDelegate.Combine (X, Y) '. Nawet bez kwestii kowariancji, wydaje się to czystsze niż '(FooDelegate) Delegate.Combine (X, Y)' i może dodać sprawdzanie w czasie kompilacji, że odpowiednie były 'X' i' Y'. – supercat
@supercat Dla mnie brzmi to jak dobre rozwiązanie. –