2011-08-16 13 views
8

Mam naprawdę dziwny problem z instrukcją warunkową podczas ustawiania wartości Action<T>. Nie chodzi o to, że nie wiem, jak sobie z tym poradzić, ponieważ jest to całkiem łatwe do rozwiązania przy użyciu zwykłego if.Polecenie warunkowe, delegat ogólny niepotrzebny rzut

Oto mój problem:

public class Test 
{ 
    public bool Foo { get; set; } 
    public Action<bool> Action { get; set; } 

    public void A() 
    { 
     Action = Foo ? B : C;//Gives compiler error 
    } 

    public void B(bool value) 
    { 

    } 

    public void C(bool value) 
    { 

    } 
} 

To daje mi błąd kompilacji z komunikatem

Nie ma niejawna konwersja między „grupą metoda” i „grupy metoda”.

Co jest dziwne, ponieważ nie rozumiem, dlaczego byłoby to nielegalne.

Nawiasem mówiąc, składnia poniżej uczyni to ważne (z punktu widzenia kompilatory):

public void A() 
    { 
     Action = Foo ? (Action<bool>) B : C; 
    } 

Więc może można przeczytać na pytanie, dlaczego jest obsada konieczne?

Odpowiedz

2

Połączyłeś dwie podobne koncepcje:

A) Grupa metod. Grupa metod to jedna lub więcej metod C# o tej samej nazwie. Jest to abstrakcja używana głównie przez kompilator; nie można omijać grupy metod. Wszystko, co możesz zrobić z grupą metod, to wywołaj ją lub utwórz z niej delegata. Możesz domyślnie utworzyć delegata z grupy metod, jeśli podpisy typu są zgodne.

B) Delegat. Wiesz, kim jest delegat; ma określony podpis typu i odnosi się bezpośrednio do metody. Oprócz wywoływania go można go przekazać i traktować jako obiekt pierwszej klasy.

W pierwszym przykładzie wyrażenie zwraca grupę metod B z jednej strony i inną grupę metod C po drugiej stronie. Operator trójskładnikowy musi zwracać ten sam typ po obu stronach, ale nie wie, na co rzucić; Typ zmiennej, któremu przypisano wynik do (Action<bool>), nie określa typu wyrażenia. To niejednoznaczne.

W drugim przykładzie legalnie rzutuje się grupę metod B na delegata Action<bool> po jednej stronie operatora trójskładnikowego. W trakcie próby ujednoznacznienia wyrażenia kompilator próbuje rzucić każdą stronę na typ drugiej strony. Może z powodzeniem przesłać grupę metod C do Action<bool>, więc robi to i wyrażenie jest poprawne.

-1

Akcja jest specyficzną klasą dla delegatów i nie ma jawnej konwersji od/do zwykłego delegata z podobnym podpisem.

+0

Myślałem, że kompilator C# jest wystarczająco inteligentny, aby sprawdzić ... –

1

Ponieważ B i C nie są delegatami. Są to grupy metod i można je w domyśle przekonwertować na delegatów (w szczególności Action<bool>), ale to nie to samo.

Typ wyrażenia warunkowego musi być spójny dla obu gałęzi, a ponieważ B i C są obecnie grupami metod (które nie są wpisane), kompilator nie może określić, jaki powinien być typ. Jak mówi, nie ma między nimi żadnej niejawnej konwersji.

Jak dobrze, nie (lub co najmniej nie) spojrzeć na drugą stronę operatora przypisania mówiąc „O powinno być Action<bool>”.

Po dodaniu obsady, rodzaj ekspresji gałęzi lewej staje Action<bool> i tam jest niejawna konwersja między grupą metoda po drugiej stronie, a delegatem, więc kompilator jest znowu szczęśliwa: typ całe wyrażenie to Action<bool>.

0

myślę, Eric will again tell me, that my reasoning is slightly incorrect, ale będę się spróbować i tak i nadzieję na jego korektę :-)

grupą sposób, na przykład B, nie ma typu, nie jest obiektem (B.GetType() nie będzie kompilował).
Można go łatwo przekonwertować na typ, dlatego istnieje niejawny rzut. Próbka:

Action<bool> a = B; // implicit cast taking place. 

Jednak jak widać w połączonej pytaniu trójskładnikowych wyrażenie próbuje znaleźć typ zwracany, że obie części meczu ekspresji. Nie wie, że później powinna nastąpić konwersja na Action<bool>.Ponieważ grupy metod nie są typami per se, nie istnieje żadna konwersja między nimi i B nie można przekonwertować na C, a zatem kompilator narzeka właśnie na to.

Przez rzutowanie dowolnej części potrójnego wyrażenia na Action<bool>, mówisz kompilatorowi, że typem zwracanym powinien być ten typ i sprawdza on, czy druga część trójskładnikowego wyrażenia obsługuje niejawną rzutowanie do tego typu. Ponieważ tak jest, kod się skompiluje.