Rozważ następujący kod:
void Handler(object o, EventArgs e)
{
// I swear o is a string
string s = (string)o; // 1
//-OR-
string s = o as string; // 2
// -OR-
string s = o.ToString(); // 3
}
Jaka jest różnica między tymi trzema rodzajami rzutów (okej, trzeci nie jest rzutem, ale masz zamiar). Który powinien być preferowany?
string s = Convert.ToString(o)
:; 5:string s = $"{o}"
(lub równoważniestring.Format
formularz dla wcześniejszego C #)Odpowiedzi:
Zgłasza wyjątek InvalidCastException, jeśli
o
nie jest tostring
. W przeciwnym razie przypisujeo
dos
, nawet jeślio
jestnull
.Przypisuje
null
dos
jeślio
nie tostring
czyo
jestnull
. Z tego powodu nie można go używać z typami wartości (null
w takim przypadku operator nigdy nie mógł wrócić ). W przeciwnym razie przypisujeo
dos
.Powoduje wyjątek NullReferenceException, jeśli
o
jestnull
. Przypisuje wszystko,o.ToString()
do czego wracas
, bez względu na typo
.Użyj 1 do większości konwersji - to proste i jednoznaczne. Zwykle prawie nigdy nie używam 2, ponieważ jeśli coś nie jest odpowiedniego typu, zwykle spodziewam się wyjątku. Widziałem tylko potrzebę tego typu funkcji return-null ze źle zaprojektowanymi bibliotekami, które używają kodów błędów (np. Return null = error, zamiast wyjątków).
3 nie jest rzutowaniem i jest tylko wywołaniem metody. Użyj go, gdy potrzebujesz reprezentacji ciągu obiektu nie będącego ciągiem.
źródło
string s = (string)o;
Użyj, gdy coś zdecydowanie powinno być drugą rzeczą.string s = o as string;
Użyj, gdy coś może być inną rzeczą.string s = o.ToString();
Użyj, gdy nie obchodzi Cię, co to jest, ale po prostu chcesz użyć dostępnej reprezentacji ciągu.źródło
To naprawdę zależy od tego, czy wiesz, czy
o
jest to łańcuch, i co chcesz z nim zrobić. Jeśli twój komentarz oznacza, żeo
tak naprawdę jest to struna, wolałbym(string)o
rzut prosty - raczej nie zawiedzie.Największą zaletą używania prostego rzutowania jest to, że gdy się nie powiedzie, otrzymujesz InvalidCastException , który mówi ci prawie, co poszło nie tak.
Z
as
operatorem, jeślio
nie jest łańcuchem,s
jest ustawiony nanull
, co jest przydatne, jeśli nie masz pewności i chcesz przetestowaćs
:Jeśli jednak nie wykonasz tego testu, użyjesz go
s
później i zostanie zgłoszony wyjątek NullReferenceException . Te wydają się być bardziej powszechne i wiele trudniej wytropić gdy tylko dzieje się w środowisku naturalnym, jak prawie każda linia dereferences zmienną i może rzucić jeden. Z drugiej strony, jeśli próbujesz rzutować na typ wartości (dowolny prymityw lub struktury takie jak DateTime ), musisz użyć prostego rzutowania -as
nie zadziała.W szczególnym przypadku konwersji na ciąg, każdy obiekt ma
ToString
, więc trzecia metoda może być w porządku, jeślio
nie jest zerowa i uważasz, żeToString
metoda może zrobić to, co chcesz.źródło
as
z zerowymi typami wartości. IEo as DateTime
nie będzie działać, aleo as DateTime?
będzie ...if (s is string)
zamiast tego?is
ing, będziesz musiał ponownie rzucić, więc masz mocną, a potem ciężką obsadę. Z jakiegoś powoduas
kontrola zerowa wydawała mi się lepsza.Jeśli już wiesz, na jaki typ może on rzutować, użyj rzutowania w stylu C:
Zauważ, że tylko z rzutowaniem w stylu C można wykonać jawny przymus typu.
Jeśli nie wiesz, czy jest to pożądany typ i zamierzasz go użyć, jeśli tak, użyj jako słowa kluczowego:
Należy zauważyć, że jak nie będzie wywoływać żadnych operatorów konwersji typu. Będzie ona różna od null tylko wtedy, gdy obiekt nie ma wartości null i natywnie określonego typu.
Użyj ToString (), aby uzyskać czytelny dla człowieka ciąg znaków reprezentujący dowolny obiekt, nawet jeśli nie można rzutować na ciąg.
źródło
Słowo kluczowe as jest dobre w asp.net, gdy używasz metody FindControl.
Oznacza to, że możesz operować na zmiennej tekstowej, a nie rzutować ją
object
tak, jak w przypadku rzutowania bezpośredniego:Nie jest to wielka sprawa, ale oszczędza wiersze kodu i przypisywanie zmiennych, a ponadto jest bardziej czytelna
źródło
„as” opiera się na „is”, które jest słowem kluczowym, które sprawdza w czasie wykonywania, czy obiekt jest polimorficznie kompatybilny (w zasadzie jeśli można wykonać rzutowanie) i zwraca wartość null, jeśli sprawdzenie się nie powiedzie.
Te dwa są równoważne:
Używanie „jako”:
Używanie „is”:
Przeciwnie, rzutowanie w stylu c jest wykonywane również w czasie wykonywania, ale zgłasza wyjątek, jeśli rzutowanie nie może być wykonane.
Aby dodać ważny fakt:
Słowo kluczowe „as” działa tylko z typami referencji. Nie możesz zrobić:
W takich przypadkach musisz użyć rzutowania.
źródło
2 jest przydatny do rzutowania na typ pochodny.
Załóżmy, że a jest zwierzęciem:
dostanie karmione minimum odlewów.
źródło
Według eksperymentów przeprowadzonych na tej stronie: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as
(czasami na tej stronie pojawiają się błędy „niedozwolonego odsyłacza”, więc odśwież ją, jeśli tak się dzieje)
Wniosek jest taki, że operator „jak” jest zwykle szybszy niż rzut. Czasem wiele razy szybszy, czasem ledwo szybszy.
Uważam peronicznie, że „jak” jest również bardziej czytelne.
Tak więc, ponieważ jest on zarówno szybszy, jak i „bezpieczniejszy” (nie rzuca wyjątku) i być może łatwiejszy do odczytania, zalecam używanie „jako” przez cały czas.
źródło
„(string) o” spowoduje wyjątek InvalidCastException, ponieważ nie ma bezpośredniego przesyłania.
„o jako ciąg” spowoduje, że s będzie odwołaniem zerowym, a nie zgłoszonym wyjątkiem.
„o.ToString ()” nie jest obsadą żadnego rodzaju per se, jest to metoda implementowana przez obiekt, a więc w taki czy inny sposób, przez każdą klasę w .net, która „robi coś” z instancją wywołana klasa i zwraca ciąg znaków.
Nie zapominaj, że do konwersji na ciąg znaków istnieje również Convert.ToString (someType instanceOfThatType), gdzie someType jest jednym z zestawu typów, głównie typów bazowych frameworka.
źródło
Wszystkie podane odpowiedzi są dobre, jeśli mogę coś dodać: Aby bezpośrednio użyć metod i właściwości ciągu (np. ToLower), nie możesz napisać:
możesz pisać tylko:
ale możesz zamiast tego napisać:
Ta
as
opcja jest bardziej czytelna (przynajmniej moim zdaniem).źródło
(o as string).ToLower()
zamiast wielu mylących nawiasów.Jest preferowany, ponieważ pozwala uniknąć kary za wydajność podwójnego rzucania.
źródło
Wygląda na to, że obie są różne pod względem koncepcyjnym.
Direct Casting
Typy nie muszą być ściśle powiązane. Występuje we wszystkich rodzajach smaków.
Wydaje się, że obiekt zostanie przekształcony w coś innego.
Operator AS
Rodzaje mają bezpośredni związek. Jak w:
Wydaje się, że będziesz obsługiwać obiekt w inny sposób.
Próbki i IL
źródło
Chciałbym zwrócić uwagę na następujące cechy operatora as :
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/ke words/as
źródło
Gdy próbuję uzyskać ciąg reprezentujący dowolny element (dowolnego typu), który potencjalnie może mieć wartość NULL, wolę poniższy wiersz kodu. Jest kompaktowy, wywołuje ToString () i poprawnie obsługuje wartości zerowe. Jeśli o ma wartość null, s będzie zawierać String.Empty.
źródło
Ponieważ nikt o tym nie wspominał, słowo kluczowe najbliższe instanceOf Java jest następujące:
źródło
Użyj rzutowania bezpośredniego,
string s = (string) o;
jeśli w logicznym kontekście Twojej aplikacjistring
jest to jedyny prawidłowy typ. Dzięki takiemu podejściu uzyskaszInvalidCastException
i wdrożysz zasadę niezawodności . Twoja logika będzie chroniona przed dalszym przekazywaniem nieprawidłowego typu lub otrzymaniem NullReferenceException, jeśli zostanie użytyas
operator.Jeśli logika oczekuje użycia kilku różnych typów
string s = o as string;
i sprawdź jąnull
lub użyjis
operatora.Nowa wersja fajna pojawiła się w C # 7.0, aby uprościć rzutowanie, a sprawdzenie to dopasowanie wzoru :
źródło
W C # obsługiwane są następujące dwie formy konwersji typu (rzutowanie):
|
(C) przeciwko
• Konwertuj typ statyczny v na c w podanym wyrażeniu
• Możliwe tylko wtedy, gdy typem dynamicznym v jest c lub podtyp c
• Jeśli nie, zgłaszany jest wyjątek InvalidCastException
|
v jako C
• Nieśmiertelny wariant (c) v
• W ten sposób przekonwertuj typ statyczny v na c w danym wyrażeniu
• Zwraca null, jeśli typem dynamicznym v nie jest c lub podtyp c
źródło