To trochę długotrwałe pytanie, więc proszę o zachowanie mnie.Lista <> Func <> s, skompiluj błąd z ogólnym typem zwracania, ale dlaczego?
Potrzebuję utworzyć odwzorowanie między zestawami łańcuchów i odpowiednimi wywołaniami metod dla każdego ciągu. Jednak natknąłem się na problem z kompilacją, wyjaśniony niżej.
W moim scenariuszu używam Dictionary<>
, ale problem istnieje tak samo dla List<>
. Dla uproszczenia używam List<>
w poniższym przykładzie.
Rozważmy te trzy klasy:
public abstract class MyBase { /* body omitted */ }
public class MyDerived1 : MyBase { /* body omitted */ }
public class MyDerived2 : MyBase { /* body omitted */ }
i sposób w innej klasie:
public class Test
{
public T GetT<T>() where T : MyBase { /* body omitted */ }
}
W innej klasy, mogę zadeklarować List<Func<MyBase>>
takiego:
public class SomeClass
{
public void SomeFunc()
{
var test = new Test();
var list1 = new List<Func<MyBase>>
{
test.GetT<MyDerived1>,
test.GetT<MyDerived2>
};
}
}
Wszystko w porządku i dobrze.
Ale co zrobić, jeśli chcę mieć funkcję powrotu rodzajowe klasy tak:
public class RetVal<T> where T : MyBase { /* body omitted */ }
public class Test
{
public RetVal<T> GetRetValT<T>() where T : MyBase
{
return null;
}
}
I chcę utworzyć równoważny List<>
użyciu tej funkcji. tj. listę >>?
public class Class1
{
public void SomeFunc()
{
var test = new Test();
var list2 = new List<Func<RetVal<MyBase>>>
{
test.GetRetValT<MyDerived1>, // compile error
test.GetRetValT<MyDerived2> // compile error
};
}
}
Dostaję błędy kompilacji Expected a method with 'RetVal<MyBase> GetRetValT()' signature
.
Czy jest jakiś sposób obejścia tego problemu, czy istnieje alternatywne podejście, za pomocą którego mogę utworzyć mój ciąg ... generyczne wywołanie metody mapowania?
Jest to kwestia wariancji. Zasadniczo 'RetVal' * nie jest * a 'RetVal '. Więcej szczegółów, kiedy mam czas. –
To, co powiedział @JonSkeet, jest prawdziwe. To prawo w języku C#. Jeśli chcesz wstawić 'RetVal' s MyDerived do 'RetVal ' s MyBase, musisz sprawić, aby 'RetVal' zaakceptował również niepoprawny rodzaj, to jest' RetVal '. Zobacz przykład tutaj: http://www.ienablemuch.com/2012/05/generics-object-orientation-untyped.html –
Mogę być całkowicie off-base na tym, ale nie byłby sam pomysł zwrotu ogólnej naruszają pojęcie, że generyczny musi (ostatecznie) rozwiązać coś, o czym wie kompilator w czasie kompilacji? To znaczy, powodem, dla którego kompilator zgłasza ten błąd, jest to, że oczekuje podania metody, która może zwrócić określony typ (co, jak rozumiem, jest przeciwieństwem tego, co próbujesz zrobić). Tylko spostrzeżenie, jak powiedziałem, może być daleko poza bazą ... –