Wygląda na to, że odpowiedź brzmi "nie".
Po wywołaniu Transform
bezpośrednio, trzeba określić parametr typu:
int i = Transform<int>("");
Tak hipotetycznie, jeśli można przekazać niekompletnie-skonstruowaną funkcję rodzajowy jak chcesz, to trzeba określić również parametry:
void GeneralizedFunction(string aStringA, string aStringB, Func<string, T> aAction)
{
A result1 = aAction<A>(aStringA);
B result2 = aAction<B>(aStringB);
// Do something with A and B here
}
Wydaje mi się, że można to hipotetycznie zrobić, jeśli C# ma taką składnię.
Ale jaki jest przypadek użycia? Oprócz przekształcenia łańcuchów do wartości domyślnej dowolnego typu, nie widzę zbyt dużego wykorzystania tego. W jaki sposób można zdefiniować funkcję, która dałaby sensowny wynik w jednym z dwóch różnych typów przy użyciu tej samej serii instrukcji?
EDIT
Analiza dlaczego nie jest to możliwe:
Kiedy użyć wyrażenia lambda w kodzie, jest kompilowany do obu delegata lub drzewa ekspresji; w tym przypadku jest to delegat. Nie możesz mieć instancji typu "otwartego"; innymi słowy, aby utworzyć obiekt z rodzaju ogólnego, należy określić wszystkie parametry typu.Innymi słowy, nie ma sposobu, aby mieć instancję delegata bez dostarczania argumentów dla wszystkich jego parametrów typu.
Jedną z przydatnych funkcji kompilatora C# są niejawne konwersje grup metod, w których nazwa metody ("grupa metod") może zostać niejawnie przekształcona w typ delegata reprezentujący jedno z przeciążeń tej metody. Podobnie, kompilator niejawnie konwertuje wyrażenie lambda na typ delegata. W obu przypadkach kompilator wysyła kod, aby utworzyć instancję typu delegata (w tym przypadku, aby przekazać ją do funkcji). Ale instancja tego typu delegata nadal musi mieć argument typu dla każdego z jego parametrów typu.
Aby przejść funkcję ogólną jako ogólną funkcję Wydaje się, że kompilator musi być w stanie przejść grupę metody lub Wyrażenie lambda sposobu bez konwersji, tak aAction
parametr miałby jakoś rodzaj "grupy metod" lub "wyrażenia lambda". Następnie niejawna konwersja do typu delegata może się zdarzyć w witrynach połączeń A result1 = aAction<A>(aStringA);
i B result2 = aAction<B>(aStringB);
. Oczywiście, w tym momencie jesteśmy dobrze we wszechświecie kontrowersyjnych i hipotetycznych.
Rozwiązanie wpadłem na obiad był to, zakładając funkcję Deserialize<T>
który pobiera ciąg zawierający dane odcinkach i zwraca obiekt typu T
:
void GeneralizedFunction<T>(string aStringA, string aStringB, Func<T, string> stringGetter)
{
A result1 = Deserialize<A>(stringGetter(aStringA));
B result2 = Deserialize<B>(stringGetter(aStringB));
}
void Example(string serializedA, string serializedB, string pathToA, string pathToB, FileInfo a, FileInfo b)
{
GeneralizedFunction(serializedA, serializedB, s => s);
GeneralizedFunction(pathToA, pathToB, File.ReadAllText);
GeneralizedFunction(a, b, fi => File.ReadAllText(fi.FullName));
}
co chodzi chcesz zrobić dokładnie? ponieważ nie chcesz podawać żadnych informacji dotyczących funkcji Transformalized, dlaczego nie zaakceptować func ponownie, biorąc ciąg i zwracając obiekt (z których każdy wie, że wszyscy są *) – Polity
Chodzi o to, że "Zrób coś z Symbol zastępczy A i B ukrywa część problematyczną. Czy A i B zawsze będą szczególnymi rodzajami? Wtedy nie potrzebujesz generycznych. Czy są to rodzaje arbitralne (być może z ograniczeniami)? Następnie "GeneralizedFunction" musi być w nich ogólna. – AakashM
A i B są konkretnymi typami, ale transformacja jest funkcją ogólną. – Max