Zrozumienie zmiennych i typów danych w C#
[[academy-video-youtube({"vid": "UntC0hoeGAQ", "start_time": "0", "title": "Zrozumienie zmiennych i typów danych w języku C#", "creator": "Tim Corey", "length": "28m 27s"})]]
W programowaniu w języku C# zmienne są podstawowymi elementami służącymi do przechowywania wartości danych. Zrozumienie, jak skutecznie definiować i używać zmiennych, ma kluczowe znaczenie dla pisania wydajnego i łatwego w utrzymaniu kodu. Zmienne mogą być różnych typów, w tym typów danych podstawowych, stałych i zmiennych typowanych dynamicznie, z których każda służy określonym celom. Dodatkowo konwersja typów, dynamiczne i var słowa kluczowe dodają elastyczność i odporność do programowania w C#.
Film Tima Coreya pt. "Dynamic vs Var w C#" zawiera kompleksowy przegląd tych pojęć. W tym artykułe omówimy kilka tematów poruszonych przez Tima, w tym:
- Różnica między Dynamic a Var
- Podstawowe typy danych
- Zmienne i stałe
- Dynamiczna automatyczna konwersja typów
- Wady dynamiki w rozwoju
- Dlaczego i kiedy używać Dynamic
- Dlaczego i kiedy używać Var
Dzięki zrozumieniu tych pojęć dzięki wyjaśnieniom Tima Coreya zyskasz głębszy wgląd w to, jak skutecznie zarządzać zmiennymi w języku C# i wykorzystywać je.
Różnica między Dynamic a Var
W C# var jest używane dla lokalnych zmiennych o typie ustalanym w czasie kompilacji, zapewniając bezpieczeństwo typów i wsparcie IntelliSense. Natomiast dynamic pozwala zmiennym omijać sprawdzanie typów w czasie kompilacji, co czyni je bardziej elastycznymi, ale z ryzykiem błędów w czasie działania i obniżoną wydajnością.
Tim Corey wyjaśnia, że var zapewnia bezpieczeństwo typów z określeniem typu w czasie kompilacji, jako że są to zmienne statyczne, podczas gdy dynamic zapewnia elastyczność z rozpoznawaniem typów w czasie wykonania, co może prowadzić do błędów w czasie działania i problemów z wydajnością.
Podstawowe typy danych
Tim rozpoczyna swoją prezentację w Visual Studio od przedstawienia podstawowych typów danych w języku C#. Tworzy obiekt dynamic nazwany testDynamic, który może otrzymać nową wartość w dowolnym czasie, a jego typ danych może dynamicznie zmieniać się w czasie działania. Jest to zademonstrowane przez poniższy kod:
// Declaration of a dynamic variable that can change types at runtime
dynamic testDynamic;// Declaration of a dynamic variable that can change types at runtime
dynamic testDynamic;Język C# udostępnia kilka podstawowych typów danych do obsługi różnego rodzaju danych. Typy całkowite obejmują int dla 32-bitowych liczb całkowitych ze znakiem, long dla 64-bitowych liczb całkowitych ze znakiem, short dla 16-bitowych liczb całkowitych ze znakiem i byte dla 8-bitowych liczb całkowitych bez znaku. Dla liczb zmiennoprzecinkowych, C# oferuje float dla pojedynczej precyzji w 32-bitach, double dla podwójnej precyzji w 64-bitach i decimal dla precyzyjnych wartości dziesiętnych w 128-bitach, idealnych do obliczeń finansowych. Typ danych char reprezentuje 16-bitowe znaki Unicode, podczas gdy typ bool jest używany dla wartości prawda lub fałsz. Dodatkowo typ danych string reprezentuje ciąg znaków, umożliwiając przechowywanie i manipulację tekstem.
Te typy danych mają fundamentalne znaczenie dla programowania w języku C#, umożliwiając wydajne przechowywanie i przetwarzanie danych, co Tim pokazuje w kolejnych przykładach. Wiele zmiennych może być zadeklarowanych i przypisanych do całkowitych typów int w jednej linii, a każdy typ danych ma domyślną wartość, jeśli nie jest wyraźnie przypisany początkową wartość. Zmienne stałe zachowują stałe wartości, zapewniając spójność w całym kodzie. Ponadto za pomocą tych typów danych można również deklarować zmienne instancji i zmienne statyczne, co zapewnia solidną i elastyczną strukturę programów.
Zmienne i stałe
Tim Corey o 1:21 próbuje stworzyć obiekt var nazwany testVar bez początkowego przypisania, co skutkuje błędem w czasie kompilacji, ponieważ var wymaga początkowego przypisania do określenia jego typu:
// This will result in a compile-time error due to lack of type inference
// var testVar;// This will result in a compile-time error due to lack of type inference
// var testVar;Skutkuje to czerwoną linią falowaną pod testVar, wskazującą błąd. O 1:55 Tim wyjaśnia, że var musi zostać przypisany typ przy deklaracji. Na przykład:
// var assignment with type inference from the initial value
var testVar = 2; // testVar is inferred to be of type int// var assignment with type inference from the initial value
var testVar = 2; // testVar is inferred to be of type intTim (2:44) demonstruje, że jeśli później spróbuje przypisać do testVar wartość zmiennoprzecinkową, powoduje to błąd, ponieważ testVar został początkowo przypisany jako int:
// Attempting to change the type from int to double causes an error
// testVar = 1.1; // Error: Cannot implicitly convert type 'double' to 'int'// Attempting to change the type from int to double causes an error
// testVar = 1.1; // Error: Cannot implicitly convert type 'double' to 'int'Tim (3:17) podkreśla, że typ var jest ustalany w momencie jego początkowego przypisania i nie może się później zmieniać. Jeśli testVar jest początkowo przypisany wartością zmiennoprzecinkową, zostanie określony jako zmiennoprzecinkowy:
// Another example with dynamic typing
var testVar = 2.1; // Now testVar is a double// Another example with dynamic typing
var testVar = 2.1; // Now testVar is a doubleChociaż Tim nie porusza tematu zmiennych stałych, są one równie ważne w programach napisanych w języku C#. Stałe w C# są deklarowane za pomocą słowa kluczowego const, po którym następuje typ danych i identyfikator zmiennej stałej, na przykład:
// Declaring a constant variable
const int MaxValue = 100;// Declaring a constant variable
const int MaxValue = 100;Stałym należy przypisać wartość w momencie deklaracji, której nie można zmienić podczas wykonywania programu, zapewniając niezmienne wartości dla logiki programu.
Dynamiczna automatyczna konwersja typów
Tim podkreśla, jak słowo kluczowe dynamic pozwala na elastyczne operowanie typami, działając nieco jak object, ale z dodatkowymi możliwościami. O 3:53, Tim demonstruje, jak dynamic bezproblemowo konwertuje między różnymi typami w czasie działania, prezentując swoje możliwości w obliczeniach z udziałem liczb całkowitych i zmiennoprzecinkowych bez jawnego rzutowania, jak pokazano w jego przykładzie kodu:
// Demonstrating dynamic type conversion at runtime
dynamic testDynamic = 1;
testDynamic = testDynamic + 2.1;
Console.WriteLine(testDynamic); // Outputs 3.1 as it converts the integer to a double// Demonstrating dynamic type conversion at runtime
dynamic testDynamic = 1;
testDynamic = testDynamic + 2.1;
Console.WriteLine(testDynamic); // Outputs 3.1 as it converts the integer to a doubleTutaj Tim (4:39) ilustruje, że testDynamic początkowo zawiera wartość całkowitą, ale bez trudu konwertuje ją na zmiennoprzecinkową, gdy dodaje do niej 2.1, co skutkuje wynikiem 3.1.
Pomimo swojej elastyczności, Tim ostrzega przed nadużywaniem dynamic z powodu kosztów wydajności wynikających z częstych konwersji typów. Podkreśla o 5:55, że dynamic powinno być stosowane oszczędnie w rozwoju C#, aby uniknąć zbędnego obciążenia procesora oraz utraty sprawdzania błędów w czasie kompilacji i wsparcia IntelliSense, co jest kluczowe dla utrzymania solidnych i bezbłędnych baz kodów.
Wady Dynamic in Development
Tim Corey ilustruje, jak dynamic może prowadzić do błędów w czasie działania i nieoczekiwanego zachowania w aplikacjach. Zaczyna od pokazania, jak zadeklarować zmienną dynamiczną i przypisać jej początkowo pusty ciąg znaków, aby uniknąć natychmiastowego błędu. Następnie próbuje wywołać nieistniejącą metodę sayHi na dynamicznej zmiennej, co nie powoduje błędu w czasie kompilacji, ale skutkuje wyjątkiem w czasie działania, pokazując kluczową wadę dynamic: brak sprawdzania w czasie kompilacji.
// Demonstrating lack of compile-time checks with dynamic
dynamic testDynamic = "";
// testDynamic.sayHi(); // Runtime error: method does not exist// Demonstrating lack of compile-time checks with dynamic
dynamic testDynamic = "";
// testDynamic.sayHi(); // Runtime error: method does not existPonadto o godz. 8:38 Tim pokazuje, w jaki sposób zmienne dynamiczne mogą zmieniać typy w czasie wykonywania, co może powodować nieoczekiwane zachowanie. Przypisuje obiekt Person do zmiennej dynamicznej, a następnie przypisuje ją ponownie do ciągu tekstowego i pokazuje, jak taka elastyczność może prowadzić do błędów logicznych i utrudniać debugowanie.
// Demonstrating the potential errors with dynamic type reassignment
dynamic testDynamic = new Person();
testDynamic = "Hi";
Console.WriteLine(testDynamic); // Works fine, but not ideal for type safety// Demonstrating the potential errors with dynamic type reassignment
dynamic testDynamic = new Person();
testDynamic = "Hi";
Console.WriteLine(testDynamic); // Works fine, but not ideal for type safetyTim wyjaśnia również, że zmienne dynamiczne nie są obsługiwane przez IntelliSense, co może prowadzić do błędów wykonania spowodowanych literówkami lub nieprawidłowymi nazwami metod. Na przykład, o 14:05, wywołuje nazwę właściwości Email, która nie istnieje, co podkreśla, jak ten błąd pozostaje niezauważony do czasu działania. Kod kompiluje się bez błędów, ale zawodzi w czasie działania, gdy metody lub właściwości oczekiwane na obiekcie Person nie zostają odnalezione na ciągu tekstowym.
// Demonstrating a runtime error due to missing property
// testDynamic.Email = "Test@test.com"; // property not found until runtime// Demonstrating a runtime error due to missing property
// testDynamic.Email = "Test@test.com"; // property not found until runtimeZalety używania słowa kluczowego Var
Natomiast var jest silnie typowany i zapewnia sprawdzanie typów w czasie kompilacji oraz wsparcie IntelliSense. Dzięki temu wszelkie problemy związane z typami danych są wykrywane na etapie tworzenia oprogramowania, co sprawia, że kod jest bardziej niezawodny i łatwiejszy w utrzymaniu. Tim Corey demonstruje to, tworząc zmienną var i przypisując do niej obiekt Person:
// Using var for strongly-typed assignments
var testVar = new Person();
testVar.FirstName = "Sue";
testVar.LastName = "Storm";
// The use of IntelliSense assists in reducing runtime errors
Console.WriteLine(testVar.SayHello()); // Ideally a method in Person class// Using var for strongly-typed assignments
var testVar = new Person();
testVar.FirstName = "Sue";
testVar.LastName = "Storm";
// The use of IntelliSense assists in reducing runtime errors
Console.WriteLine(testVar.SayHello()); // Ideally a method in Person classPróba wywołania nieistniejącej metody lub ponownego przypisania zmiennej var do innego typu zostanie uchwycona w czasie kompilacji, zapobiegając potencjalnym błędom w czasie działania.
// Attempting to change type results in compile-time errors with var
// testVar = "Hi"; // Compile-time error// Attempting to change type results in compile-time errors with var
// testVar = "Hi"; // Compile-time errorTyp zwracanej wartości metody
O 15:05 Tim demonstruje, że można również zwrócić typ dynamic z metody, ale nie można zwrócić var. Na przykład:
// Method returning a dynamic type
public dynamic GetMessage() {
return "This is a test";
}// Method returning a dynamic type
public dynamic GetMessage() {
return "This is a test";
}Próba zwrócenia var spowodowałaby błąd w czasie kompilacji, ponieważ sygnatura metody musi precyzować konkretny typ zwracany.
Dlaczego i kiedy używać Dynamic
Tim rozwija temat specyficznych scenariuszy, w których dynamic staje się niezbędny. Wyjaśnia on, że C# jest zasadniczo językiem silnie typowanym, co oznacza, że każdej zmiennej przypisany jest określony typ, który pozostaje niezmienny przez cały jej cykl życia. Stanowi to kontrast w stosunku do języków takich jak JavaScript, w których zmienne mogą dynamicznie zmieniać typy.
Tim, o godz. 18:14, wyjaśnia, że chociaż język C# jest zaprojektowany z myślą o zmiennych silnie typowanych, istnieją sytuacje, zwłaszcza podczas interakcji z systemami zewnętrznymi lub językami takimi jak Python, Ruby lub obiektami COM, w których typowanie dynamiczne może być korzystne. Używa przykładu integracji API Pythona, aby podkreślić praktyczną potrzebę dla dynamic. W takich przypadkach posiadanie elastycznego systemu typów, który może dostosować się do różnych typów danych z zewnętrznych źródeł, upraszcza interakcję.
Tim Corey o 18:44 podkreśla, że chociaż dynamic jest przydatny dla interakcji międzylangowych, zazwyczaj nie jest zalecany dla czysto kodu C# z powodu utraty sprawdzania błędów w czasie kompilacji i wsparcia IntelliSense. Ostrzega, że elastyczność dynamic wiąże się z kosztem wydajności i bezpieczeństwa typów, czyniąc go mniej pożądanym wyborem dla regularnego programowania C# tam, gdzie należy preferować zmienne silnie typowane.
Dlaczego i kiedy używać słowa kluczowego Var
Następnie Tim omawia użycie i filozofię za var słowem kluczowym w C#. Zauważa, że istnieją dwa główne obozy w kwestii używania var: ci, którzy preferują go używać wyłącznie, oraz ci, którzy wolą jawne deklaracje typów.
Tim o 19:43 wyjaśnia, że zwolennicy var argumentują, że sprzyja to lepszym konwencjom nazewnictwa, czyniąc kod samodokumentującym się. Uważają oni, że nazwy zmiennych powinny być na tyle opisowe, aby przekazywały typ bez konieczności wyraźnej deklaracji.
Z drugiej strony (20:46) zwolennicy jawnych deklaracji typów argumentują, że widoczność rzeczywistego typu bezpośrednio w kodzie pozwala od razu rozpoznać, jaki jest typ zmiennej lokalnej, bez konieczności najeżdżania kursorem na zmienną w celu sprawdzenia jej typu. Na przykład:
// Explicit type declaration provides clarity
string firstName = "Tim";// Explicit type declaration provides clarity
string firstName = "Tim";Jest to preferowane przez niektórych, ponieważ usuwa wszelkie wątpliwości co do typu zmiennej.
Tim podziela swoje zrównoważone podejście o 21:15, stwierdzając, że zazwyczaj używa jawnego typowania dla typowych typów danych, takich jak string, int, double i decimal, ponieważ to czyni kod bardziej przejrzystym i unika potencjalnych problemów, takich jak pomieszanie double i decimal. Na przykład:
// Explicit type ensures there's no ambiguity between float types
double myMoney = 1.1; // This is a double
decimal myMoney = 1.1M; // This is a decimal// Explicit type ensures there's no ambiguity between float types
double myMoney = 1.1; // This is a double
decimal myMoney = 1.1M; // This is a decimalTim podkreśla, że jawne deklarowanie typu zapewnia użycie właściwego typu, zwłaszcza gdy może dojść do zamieszania między podobnymi typami.
Jednakże Tim również przyznaje, że var może być szczególnie przydatne przy pracy z długimi lub skomplikowanymi typami. Podaje przykład o 23:37, gdzie deklaracja List<List<Person>> może być rozbudowana:
// Declaring a complex type using var
var rounds = new List<List<Person>>();// Declaring a complex type using var
var rounds = new List<List<Person>>();Również demonstruje jego użyteczność w pętlach foreach (23:55):
// Utilizing var in loop for cleaner code
foreach (var round in rounds) {
// Do something with each round
}// Utilizing var in loop for cleaner code
foreach (var round in rounds) {
// Do something with each round
}Tim podsumowuje, zauważając, że chociaż var może redukować rozbudowanie, kluczowe jest zapewnienie, że nazwy zmiennych są jasne i opisowe, aby utrzymać czytelność i unikać zamieszania.
Równoważąc użycie var z jawnymi typami, programiści mogą pisać jasny, łatwy do zarządzania i wydajny kod, wykorzystując zalety obu podejść odpowiednio do kontekstu.
Var jako anonimowy obiekt
Tim omawia użycie var dla sytuacji, w których typ nie jest wyraźnie znany lub podczas pracy z typami anonimowymi. Demonstruje to, tworząc na miejscu anonimowy obiekt, który nie ma zdefiniowanego z góry typu. Oto kod, którego używa:
// Creating an anonymous object with var
var myItem = new { FirstName = "Tim", Email = "test@test.com" };// Creating an anonymous object with var
var myItem = new { FirstName = "Tim", Email = "test@test.com" };Tim o 25:30 wyjaśnia, że jako obiekt jest anonimowy i nie ma określonej nazwy typu, jedynym sposobem na zadeklarowanie zmiennych dla niego jest użycie var. To podejście pozwala na tworzenie i używanie obiektów bez potrzeby definiowania formalnej klasy.
Aby zilustrować, jak to działa w praktyce, Tim pisze (25:52):
// Outputting properties of an anonymous object
Console.WriteLine($"Hello {myItem.FirstName}: your email is {myItem.Email}");// Outputting properties of an anonymous object
Console.WriteLine($"Hello {myItem.FirstName}: your email is {myItem.Email}");Kiedy uruchamia kod o 26:25, wyjściem jest:
To demonstruje, że var może obsługiwać właściwości anonimowego obiektu, a Visual Studio dostarcza wsparcie IntelliSense dla tych właściwości, pomimo że obiekt jest anonimowy.
Tim o 26:54 wyjaśnia, że woli używać jawnych typów dla prostych i typowych typów, takich jak string, liczby całkowite i instancje klas, ponieważ czyni to kod bardziej przejrzystym. Jednakże używa var w przypadkach, gdy typ jest albo długi, skomplikowany, albo nie jest wyraźnie znany, na przykład przy typach anonimowych lub złożonych deklaracjach typów.
Wnioski
I oto jest - jasne zrozumienie zmiennych C# i typów danych wraz z strategicznym użyciem var i dynamic słów kluczowych. Korzystając z zrównoważonego podejścia Tima Corey'a, możesz zapewnić bezpieczeństwo typów i klarowność w twoim kodzie za pomocą słowa kluczowego var, jednocześnie wykorzystując elastyczność słowa kluczowego dynamic w specyficznych scenariuszach, takich jak interakcje z zewnętrznymi systemami.
Aby uzyskać bardziej szczegółowe informacje, koniecznie obejrzyj wideo Tima Coreya na temat "Dynamic vs Var in C#" i sprawdź jego kanał YouTube po dalsze tematy związane z nauką C#.




