10. Typy proste i referencyjne

10. Typy proste i referencyjne

 Daniel Celeda
Daniel Celeda
00:00
31.01.2006
25 komentarzy
158620 wyświetleń

W C#, tak jak w innych językach obiektowych, mamy typy proste i referencyjne.

Do typów prostych należą dane liczbowe takie jak: „int”, „float”, itd., a także typy wyliczeniowe oraz struktury („string” to struktura, a więc jest typem prostym). Przypisując do jednej zmiennej prostej jakąś wartość lub wartość z innej zmiennej prostej, tworzy się kopia.  W  przypadku referencji nie powstaje kopia danych, lecz kopiuje się tzw. wskaźnik na dane, czyli wskazanie na jakie dane zmienna wskazuje. Spróbuję to zobrazować przykładami.

Najpierw przyjrzyjmy się operacjom na typach prostych.

class KlasaGlowna
{
    static void Main()
    {
        int x = 2;
        int y = x;
        x = x + 8;

        System.Console.WriteLine("Wartość x: " + x);
        System.Console.WriteLine("Wartość y: " + y);
        System.Console.ReadLine();
    }
}

Na początku przypisujemy wartość 2 do zmiennej “x”, następnie kopię wartości “x” (w zasadzie wartości 2 znajdującej się w zmiennej “x”) zmiennej “y”. Na koniec zwiększamy wartość zmiennej „x” o 8 i wypisujemy zawartości obu zmiennych na ekranie.

Widać, że zmiana wartości zmiennej „x” nie miała wpływu na wartość zmiennej „y”.
Zupełnie inaczej jest w przypadku zmiennych referencyjnych.

class KlasaPomocnicza
{
    public int x;
}
class KlasaGlowna
{
    static void Main()
    {
        KlasaPomocnicza obiekt1 = new KlasaPomocnicza();
        KlasaPomocnicza obiekt2 = new KlasaPomocnicza();

        obiekt1.x = 2;
        obiekt2 = obiekt1;
        obiekt1.x = obiekt1.x + 8;

        System.Console.WriteLine("Wartość x w obiekcie pierwszym: " + obiekt1.x);
        System.Console.WriteLine("Wartość x w obiekcie drugim: " + obiekt2.x);
        System.Console.ReadLine();
    }
}

Wynik wykonania powyższego programu może być zaskakujący.

Zwiększaliśmy wartość „x” tylko w obiekcie pierwszym, jednak zwiększyła się też wartość „x” w obiekcie drugim. Stało się tak dlatego, ponieważ obiekty to typy referencyjne. W linijce

obiekt2 = obiekt1;

określiliśmy, że obydwa obiekty wskazują na to samo miejsce w pamięci, a więc każda zmiana danych wskazywanych przez jeden z obiektów, powoduje zmianę danych wskazywanych przez drugi (jest to oczywistem, ponieważ są to te same dane).

@STRONA@

Rzutowanie

Typy „z tej samej rodziny” możemy rzutować jeden na drugi. Np. typ „long” na „int”

class KlasaGlowna
{
    static void Main()
    {
        long x = 2;
        int y = (int)x;
    }
}

lub „int” na „long”

class KlasaGlowna
{
    static void Main()
    {
        int x = 2;
        long y = (long)x;
    }
}

Jednak pierwszy przypadek jest niepoprawny, ponieważ typ „long” jest dokładniejszy od „int” i podczas rzutowania możemy utracić poprawność danych.

Konwersja między typami

Konwersja służy do konwertowania typów z jednego na drugi. W części kursu poświęconej łańcuchom znakowym konwertowaliśmy wartości liczbowe na typ „string” podczas łączenia łańcuchów za pomocą operatora „+”. Była to konwersja niejawna, czyli taka, której sami nie wywołaliśmy. Kompilator sam rozpoznał, że musi skonwertować typ liczbowy na „string”. Napiszmy krótki program konwertujący łańcuch znakowy na typ liczbowy.

class KlasaGlowna
{
    static void Main()
    {
        System.Console.WriteLine("Podaj liczbę.");
        string napis = System.Console.ReadLine();
        int x = int.Parse(napis);
        int wynik = x * 2;
        System.Console.WriteLine("Liczba " + x + " pomnożona przez 2 " + "równa się " + wynik);
        System.Console.ReadLine();
    }
}

„Int” posiada statyczną metodę „Parse(string parametr)”, która jako parametr przyjmuje łańcuch znakowy, który następnie konwertuje na typ całkowitoliczbowy.

Jeśli łańcuch znakowy nie będzie liczbą, (np. podamy zamiast liczby literę „s”) otrzymamy błąd podczas wykonania programu.
W .NET mamy bardzo przydatna klasę „Convert”, która posiada wiele metod statycznych do konwersji typów. Działanie tych metod możemy zobrazować poniższym przykładem.

class KlasaGlowna
{
    static void Main()
    {
        System.Console.WriteLine("Podaj liczbę.");
        string napis = System.Console.ReadLine();
        int x = System.Convert.ToInt32(napis);
        int wynik = x * 2;
        System.Console.WriteLine("Liczba " + x + " pomnożona przez 2 " + "równa się " + wynik);
        System.Console.ReadLine();
    }
}

Wynik jaki otrzymamy powinien być taki sam, jak w poprzednim programie.

@STRONA@

Proste typy danych w C#

Warto poznać kilka z wbudowanych prostych typów danych w C#.

bool – typ logiczny, oznaczający prawdę („true”) lub fałsz („false”), używany do operacji logicznych,
short
– 16-bitowa liczba całkowita,
int
– 32-bitowa liczba całkowita,
long
– 64-bitowa liczba całkowita,
float
– 32-bitowa liczba zmiennoprzecinkowa,
double
– 64-bitowa liczba zmiennoprzecinkowa,
char
– pojedynczy znak zapisany w formacie Unicode,
string
– łańcuch znakowy, zbiór znaków w formacie Unicode.

Stałe

Stałe to dane, których wartości nie możemy zmieniać. W pewnym uproszczeniu możemy sobie wyobrazić, że są to zmienne, których wartości są zawsze takie same. Ze stałymi związane jest słówko „const”, które definiuje nam stałą.

class KlasaGlowna
{
    public const double PI = 3.14;
    public const double E = 2.74;

    static void Main()
    {
        System.Console.WriteLine("Liczba PI ma warość: " + PI);
        System.Console.WriteLine("Liczba e ma wartość: " + E);
        System.Console.ReadLine();
    }
}

Wygodniej jest stworzyć klasę ze stałymi, którą możemy wykorzystać w wielu innych klasach (a nawet programach).

class Liczby
{
    public const double PI = 3.14;
    public const double E = 2.74;
}

class
KlasaGlowna
{
    static void Main()
    {
        System.Console.WriteLine("Liczba PI ma warość: " + Liczby.PI);
        System.Console.WriteLine("Liczba e ma wartość: " + Liczby.E);
        System.Console.ReadLine();
    }
}

Ponieważ „PI” oraz „E” są stałymi, nie musimy tworzyć obiektów klasy „Liczby” – wartości tych stałych będą zawsze dostępne i niezmienne.
A oto wynik działania obydwu powyższych programów.


Spodobał Ci się ten artykuł? Podziel się z innymi!

Źródło:

Polecamy również w kategorii Kurs C#, cz. I

Komentarze

  • Shreeve 07:54 27.07.2006

    Kod działa, ale zastanawia mnie, w jaki sposób mamy dostęp do zmiennych klasy, bez tworzenia jej instancji, lub bez oznaczania jej jako static, tym bardziej, że jest dostęp poprzez nazwę klasy?

  • nj 11:40 29.07.2006

    @Shreeve: "KlasaPomocnicza obiekt1 = new KlasaPomocnicza(); KlasaPomocnicza obiekt2 = new KlasaPomocnicza();" Te linie tworzą dwie nowe instancje klasy KlasaPomocnicza: obiekt1 i obiekt2... Dzięki temu, że zmienna x NIE jest statyczna, każda instancja przechowuje swoją wartość iksa, do którego dostęp mamy przez nazwę instancji, np. obiekt1.x - mam nadzieję, że rozjaśniłem. Pozdrawiam :)

  • Wujek 20:48 05.08.2006

    Błąd w kodzie; pierwsze okno int x = 2; int y = x; x = x + 8; powinno być: int x = 2; int y = x; y = x + 8;

  • Ciocia 12:38 10.08.2006

    Sam jestes błąd w kodzie

  • Wujek 17:01 10.08.2006

    Ty ciotka nie podskakuj bo ci zaraz zrobie masowanie jąder

  • kostii 11:56 11.08.2006

    nie błąd w kodzie tylko źle zrozumiałes lekcje

  • Kazik 14:24 14.08.2006

    Tak jest!!! Pała!!! Źle zrozumiałeś :) lol

  • Wujek 17:09 18.08.2006

    Przepraszam wszystkich za moje wybryki na forum, oczywiście, że jest bład z mojej strony. Pozdro. Po prostu zwiększamy x'a o 8

  • bartek 16:33 21.08.2006

    Cytat: Stałe to dane, których wartości nie możemy zmieniać. W pewnym uproszczeniu możemy sobie wyobrazić, że są to zmienne, których wartości są zawsze takie same. Koniec cytatu. Jeżeli stała to nie zmienna!!! Cytat: W C#, tak jak w innych językach obiektowych, mamy typy proste i referencyjne. Koniec cytatu. Tak w C# mamy typy proste, javie też, ale nie jest to regułą w językach obiektowych!!!!!!!

  • yaro27 15:26 11.07.2008

    String typem prostym?? Raczej referencyjnym. Poniższy link wszystko wyjaśnia: http://www.microsoft.com/poland/developer/net/podstawy/clr.mspx

  • nie 14:19 16.09.2008

    <p>[img]../tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif[/img]</p>

  • carck3r 21:35 01.05.2009

    <p>Błąd - string jest typem referencyjnym. Dowód: http://msdn.microsoft.com/en-us/library/490f96s2.aspx</p>

  • Programista C++ 10:49 23.07.2009

    <p>Cytat:</p> <p><span>określiliśmy, że obydwa obiekty wskazują na to samo miejsce<br />w pamięci, a więc każda zmiana danych wskazywanych przez jeden z obiektów,<br />powoduje zmianę danych wskazywanych przez drugi </span></p> <p> </p> <p>Chyba szkoda czasu na ten kurs. Obiekty na coś wskazują? obiekt1 i obiekt2 to nie obiekty tylko referencje do obiektów. A tak BTW po wykonaniu linii <span><code>biekt2 = obiekt1; w pamięci nie ma już dwóch obiektów tylko jeden, bo drugi zostanie usunięty przez GC. Żenada.<br /></code></span></p>

  • DOŚWIADCZONY programista C# 10:49 24.09.2009

    Cytat: "Do typów prostych należą dane liczbowe takie jak: „int”, „float”, itd., a także typy wyliczeniowe oraz struktury („string” to struktura, a więc jest typem prostym)" Bzdura! Jak już kilka osób wpomniało string jest oczywiście typem referencyjnym jednak jego zachowanie zostało zaimplementowane tak jak struktury, tj. przeciążony został m. in. operator przypisania, który tworzy nowy obiekt string"a. Ponadto największym błędem tego artykułu jest stwierdzenie, że typami prostymi są również wypy wyliczeniowe i struktury (!). Typy proste to NIEKTÓRE struktury, dla których istnieją aliasy, np. dla struktury System.Int32 istnieje alias int, dla System.Double - double, dla System.Int64 - long itp. Ponadto typy proste rządzą się swoimi zasadami: http://msdn.microsoft.com/en-us/library/aa691144(VS.71).aspx

  • DOŚWIADCZONY programista C# 10:55 24.09.2009

    I jeszcze jedno - autorowi tego artykułu radzę zdobycie większego doświadczenia w programowaniu w platformie .NET przed napisaniem kolejnego artykułu. Wprawdzie minęło już sporo czasu od publikacji tego artykułu jednak to tyczy się każdego innego zagadnienia, gdyż wiele niedoświadczonych osób zagląda tutaj i bierze ten arykuł za pewnik opowiadając innym podobne brednie. Wydaje misię, że należy rozpatrzyć usunięcie tego artukułu lub poprawienie go przez doświadczoną osobę.

  • nos 15:45 02.11.2009

    Dla "DOŚWIADCZONEGO programisty C#" być może są tu jakieś niścisłości, ale dla początkującego, nie ma znaczenia, czy nazwywa się to tak, czy siak. Akurat w tym przypadku chodzi o przyswojenie tych pojeć, a nie o nazwanie ich. To bardzo początkujący kurs i lepiej go nie usuwajcie (błędy można poprawić :)).

  • StWolf 11:26 06.11.2009

    Witam Wlasnie korzystalem z tego artykulu, cos mi nie pasowalo i dzieki niebiosom przeczytalem komentarze... Z mojego punktu widzenia, taki artykul dyskwalifikuje w nauce jezyka! Powód to prawdziwe informacje z zaszytymi powaznymi bledami w tutku, ktore dla swiezaka ( jak ja ;] ) zapadaja dlugo w pamieci, trudno je potem naprostować! Bardzo mi przykro zolta kartka dla twórcy się należy.

  • Ryszard 13:44 26.01.2010

    Kurs jest niezwykle prosty, a zarazem merytoryczny, bardzo czytelny i zrozumiały. Czuje się, że Autor jest bardzo dobrym programistą a mimo to nie "cwaniakuje" popisując się swoją wiedzą. Dziękuję!

  • wiki 13:58 12.09.2010

    a ja już się poddaję, dalej nie idę, jak dla mnie jest  lekko chaotyczny, już nie trawię tego, kurs napisany 5 lat temu, teraz mammy 2010r, czy nic sie nei zmieniło do tego czasu w C# i nei powinno być zaktualizowane???

  • nie 10:11 25.11.2010

    nie ten poziom :D

  • marco 00:00 27.11.2010

    Czy w pierwszym przykładzie nie mamy klasycznego wycieku pamięci? Oczywiście w tak trywialnym przykładzie to nie problem ale czemu tego uczyć? Nie lepiej było napisać tak? KlasaPomocnicza obiekt1 = new KlasaPomocnicza(); KlasaPomocnicza obiekt2;

  • Krzys 11:56 01.03.2011

    marco, jak już sygnalizujesz jakiś problem to może opisałbyś go dokładniej? Wiele osób pisze tutaj, że kurs jest kiepski, że trzeba go wywalić, a może po prostu poprawiajcie błędy, albo napiszcie swój idealny tutorial?

  • Tomcio 20:14 07.08.2011

    Autorowi może chodzilo o inna liczbe (wlasna), ale liczba e to w przyblizeniu 2,71, a nie 2,74:)

  • Piotr W. 10:25 18.12.2014

    Od kiedy string jest typem prostym? http://msdn.microsoft.com/pl-pl/library/system.string%28v=vs.110%29.aspx

  • Wojciech 15:20 25.11.2015

    Pamietajcie aby stosować stałe, dlatego, że zajmuje to mniej miejsca w pamieci niz zwykla zmienna w klasie :)

Skomentuj

Autor