Jest to prawdopodobnie pytanie nowicjusza, ale Google, co zaskakujące, nie udzieliło odpowiedzi.
Mam tę raczej sztuczną metodę
T HowToCast<T>(T t)
{
if (typeof(T) == typeof(string))
{
T newT1 = "some text";
T newT2 = (string)t;
}
return t;
}
Pochodząc z tła C ++, spodziewałem się, że to zadziała. Jednak kompilacja nie powiodła się z opcją „Nie można niejawnie przekonwertować typu„ T ”na łańcuch” i „Nie można przekonwertować typu„ T ”na ciąg znaków” dla obu powyższych przypisań.
Albo robię coś złego koncepcyjnie, albo po prostu mam złą składnię. Proszę, pomóż mi to rozwiązać.
Dziękuję Ci!
typeof(T) == typeof(string)
jest rozpoznawane w czasie wykonywania, a nie w czasie kompilacji. Dlatego następujący wiersz w bloku jest nieprawidłowy.Odpowiedzi:
Mimo że jest wewnątrz z
if
bloku, kompilator nie wie, żeT
jeststring
.Dlatego nie pozwala ci rzucać. (Z tego samego powodu, że nie może oddać
DateTime
dostring
)Musisz rzucać do
object
(do którego każdyT
może rzucać), a stamtąd dostring
(ponieważobject
można rzucać dostring
).Na przykład:
źródło
T
:var isBlank = (userDefinedValue is string) && String.IsNullOrWhiteSpace(userDefinedValue as string);
Obie linie mają ten sam problem
Kompilator nie wie, że T jest ciągiem znaków, więc nie ma możliwości wiedzieć, jak to przypisać. Ale skoro sprawdziłeś, możesz to po prostu wymusić
nie musisz rzucać t, ponieważ jest to już ciąg, musisz również dodać ograniczenie
źródło
Znam podobny kod, który OP zamieścił w tym pytaniu z generycznych parserów. Z punktu widzenia wydajności należy użyć
Unsafe.As<TFrom, TResult>(ref TFrom source)
, które można znaleźć w pakiecie NuGet System.Runtime.CompilerServices.Unsafe . Pozwala to uniknąć pakowania typów wartości w tych scenariuszach. Myślę też, żeUnsafe.As
skutkuje to mniejszą ilością kodu maszynowego produkowanego przez JIT niż dwukrotne rzutowanie (przy użyciu(TResult) (object) actualString
), ale nie sprawdziłem tego.Unsafe.As
zostaną zastąpione przez JIT z wydajnymi instrukcjami kodu maszynowego, jak widać w oficjalnym repozytorium CoreFX:źródło
Jeśli szukasz jawnych typów, dlaczego deklarujesz te zmienne jako
T
?źródło
T
.object
wartości, z typami pochodnymi, które przechowująstring
wartości. Załóżmy, że te pola mają również wartość „DefaultIfNotProvided”, więc musisz sprawdzić, czy wartość podana przez użytkownika (która może być obiektem, ciągiem lub nawet liczbowym prymitywem) jest równoważnadefault(T)
. Ciąg może być traktowany jako specjalny przypadek, w którym pusty / biały ciąg jest traktowany tak samo jak domyślny (T), więc możesz chcieć sprawdzić, czyT userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace(userValue as string);
.Otrzymasz również ten błąd, jeśli masz ogólną deklarację zarówno dla swojej klasy, jak i metody. Na przykład poniższy kod podaje ten błąd kompilacji.
Ten kod nie kompiluje się (uwaga T została usunięta z deklaracji metody):
źródło
Zmień tę linię:
Dla tej linii:
źródło