j4ggi

c# typ wartości vs typ referencji

Mar 27th, 2018
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.06 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7.  
  8. namespace ValueType
  9. {
  10.     //niefortunna nazwa. istnieje klasa specjalna o nazwie ValueType, więc dodałem _ pomiędzy. nie powinno to tak wyglądać
  11.     public class Value_Type
  12.     {
  13.         int[] _arrField;
  14.  
  15.         //tu mamy pola, którym nie przypisaliśmy wartości.
  16.         //ponieważ to są pola a nie zwykłe zmienne, każde z nich zostaje zainicjalizowane (podczas tworzenia obiektu klasy Value_Type)
  17.         //za pomocą default(int), czyli 0
  18.         int a, b, c, d;
  19.         public Value_Type()
  20.         {
  21.             //teraz kopiujemy WARTOŚCI - NIE tworzymy referencji do obiektów, bo int dziedziczy po struct
  22.             //czyli - skoro mamy same zera, to nasza tablica
  23.             this._arrField = new[] { a, b, c, d };
  24.             //przyjmie wartości
  25.             //_arrField = new[] { 0, 0, 0, 0 };
  26.             foreach(var value in this._arrField)
  27.             {
  28.                 Console.WriteLine(value);
  29.             }
  30.             //0
  31.             //0
  32.             //0
  33.             //0
  34.  
  35.             //nawet jeżeli teraz przypiszemmy do pol wartości
  36.             a = 1;
  37.             b = 2;
  38.             c = 3;
  39.             d = 4;
  40.             //to nic nam to nie da (jeśli chodzi o tablicę _arrField)
  41.             //ponieważ już SKOPIOWALIŚMY WARTOŚCI, które wtedy wynosiły 0,
  42.             //więc nasza tablica NADAL wygląda tak samo
  43.             //{ 0, 0, 0, 0 };
  44.  
  45.             //ale, jeżeli teraz spróbujemy zrobić jeszcze raz tablicę
  46.             this._arrField = new[] { a, b, c, d };
  47.             //to też skopiujemy wartości zz pól abcd, tylko że tym razem mają one jakąś konkretną wartość, więc skopiujemy te wartości
  48.             //czyli teraz ta tablica będzie wyglądać o tak:
  49.             //{ 1, 2, 3, 4 }
  50.  
  51.             foreach (var value in this._arrField)
  52.             {
  53.                 Console.WriteLine(value);              
  54.             }
  55.             //1
  56.             //2
  57.             //3
  58.             //4
  59.  
  60.             //zwracam uwagę, że w żaden sposób nie możemy zmienić wartości obiektów, na które wskazują zmienne a b c d
  61.             //czyli znowu, jeżeli napiszemy
  62.             a = 1333;
  63.             b = 24;
  64.             c = 335;
  65.             d = 4466;
  66.             //to w tablicy NIC nam się nie zmieni
  67.             //ponieważ nie zmieniliśmy wartości obiektów które pamiętamy, tylko STWORZYLIŚMY NOWE obiekty
  68.             //i przypisaliśmy je do zmiennych
  69.             //tym samym straciliśmy odniesienia do starych obiektów
  70.  
  71.  
  72.             //w tablicy mamy WARTOŚCI
  73.             //więc jeżeli napiszę coś takiego
  74.  
  75.             var temp = this._arrField.Last();
  76.  
  77.             //to
  78.             //temp = 4
  79.             //ale jeżeli zmienię
  80.             this._arrField[3] = 123;
  81.             //to NADAL
  82.             //temp = 4
  83.             //ponieważ SKOPIOWALIŚMY wartość          
  84.  
  85.                        
  86.             //NIE da się zmienić wartości obiektów ValueType w c#
  87.         }
  88.     }
  89.  
  90.     //pomocnicza klasa do drugiego przykładu
  91.     public class HelperClass
  92.     {
  93.         public int Value { get; set; }
  94.     }
  95.  
  96.     //zachowałem nazewnictwo z tego, co mam powyżej, ale to jest brzydkie i unikać tego
  97.     public class Reference_Type
  98.     {
  99.         HelperClass[] _arrField;
  100.  
  101.         //znowu, jak wyżej
  102.         //tu mamy pola, którym nie przypisaliśmy wartości.
  103.         //ponieważ to są pola a nie zwykłe zmienne, każde z nich zostaje zainicjalizowane
  104.         //(podczas tworzenia obiektu klasy Reference_Type)
  105.         //za pomocą default(HelperClass), czyli null
  106.         HelperClass a, b, c, d;
  107.         public Reference_Type()
  108.         {
  109.             //ponieważ każda klasa jest (użycie słowa kluczowego class) ReferenceType - tworzymy nowe referencje do obiektów a,b,c,d
  110.             _arrField = new[] { a, b, c, d };
  111.  
  112.             //aktualnie nasza tablica wygląda tak:
  113.             //{null, null, null, null}
  114.  
  115.             //jak w poprzednim przykładzie, przypisanie do abcd aktualnie nic nam nie da
  116.             a = new HelperClass { Value = 5 };
  117.             Console.Write(_arrField[0]);
  118.             //null
  119.  
  120.             //ponieważ do zmiennej a przypisaliśmy nowy obiekt, a w tablicy została referencja do starego (tzn został null)
  121.             //więc próba
  122.             //Console.Write(_arrField[0].Value);
  123.             //wyrzuciłaby nam NullReferenceException
  124.  
  125.             //czyli - żeby nie było wątpilowści
  126.             //po przypisaniu do zmiennych REFERENCJI do NOWYCH obiektów
  127.             b = new HelperClass { Value = 55 };
  128.             c = new HelperClass { Value = 57 };
  129.             d = new HelperClass { Value = 59 };
  130.             //nasza tablica nadal wygląda tak
  131.             //{null, null, null, null}
  132.  
  133.  
  134.             //ale - jeżeli teraz przypiszemy
  135.             _arrField = new[] { a, b, c, d };
  136.             //to obiekty abcd już istnieją, więc przepisaliśmy referencje
  137.             //czyli nasza tablica wygląda tak:
  138.             //{
  139.             //  HelperClass{ Value = 5 },
  140.             //  HelperClass{ Value = 55 },
  141.             //  HelperClass{ Value = 57 },
  142.             //  HelperClass{ Value = 59 }
  143.             //}
  144.  
  145.  
  146.             //Teraz, jeżeli istnieją obiekty w pamięci i mamy w kodzie do nich referencje (które przechowujemy w zmiennych a b c d)
  147.             //możemy zmienić wartości obiektów
  148.             a.Value = 135;
  149.             //czyli - w zmiennej a oraz w pierwszym elemencie tablicy przechowujemy referencje do tego samego obiektu
  150.             //więc
  151.             //a = HelperClass{ Value = 135 }
  152.  
  153.             //oraz nasza tablica
  154.             //{
  155.             //  HelperClass{ Value = 135 },
  156.             //  HelperClass{ Value = 55 },
  157.             //  HelperClass{ Value = 57 },
  158.             //  HelperClass{ Value = 59 }
  159.             //}
  160.  
  161.             //ALE
  162.             //jeżeli stworzymy nowy obiekt w pamięci i nadpiszemy referencję którą przechowywaliśmy w zmiennej
  163.             b = new HelperClass { Value = 444 };
  164.             //to w tablicy nic nam się nei zmieni
  165.             //{
  166.             //  HelperClass{ Value = 135 },
  167.             //  HelperClass{ Value = 55 },
  168.             //  HelperClass{ Value = 57 },
  169.             //  HelperClass{ Value = 59 }
  170.             //}
  171.             //ponieważ w tablicy została nam referencja do starego obiektu
  172.             //natomiast do zmiennej b przypisaliśmy nową referencję która odnosi się do zupełnie innego obiektu w pamięci
  173.  
  174.             //w tym momencie zmiana wartości
  175.             b.Value = 32;
  176.             //nic nam nie zmieni w tablicy, ale oczywiscie zmieni nam wartość obiektu b
  177.             //b = HelperClass{ Value = 32 }
  178.  
  179.  
  180.             //mamy w tablicy REFERENCJE do obiektów
  181.             //więc jeżeli zrobię coś takiego
  182.             var temp = this._arrField.Last();
  183.             //to w temp będę miał referencję do tego samego obiektu, do którego referencję przechowuję w ostatnim
  184.             //elemencie tablicy czy zmiennej d
  185.             //czyli zmienna temp
  186.             //temp = new HelperClass { Value = 59 };
  187.             //tak samo jak
  188.             //d = new HelperClass { Value = 59 };
  189.             //tak samo jak
  190.             //this._arrField[3] = new HelperClass { Value = 59 };
  191.  
  192.             //i skoro to są referencje do tego samego obiektu, to pisząc
  193.             temp.Value = 6565;
  194.             //zmieniam właściwość Value w tym obiekcie, ale nie zmieniam samego obiektu
  195.             //więc
  196.             //temp = new HelperClass { Value = 6565 };
  197.             //tak samo jak
  198.             //d = new HelperClass { Value = 6565 };
  199.             //tak samo jak
  200.             //this._arrField[3] = new HelperClass { Value = 6565 };
  201.  
  202.  
  203.             //PISZĄC
  204.             c = new HelperClass { Value = 32 };
  205.             //po pierwsze
  206.             //tworzymy NOWY OBIEKT w pamięci
  207.             //po drugie
  208.             //przypisujemy REFERENCJĘ do ZMIENNEJ
  209.         }
  210.     }
  211. }
Advertisement
Add Comment
Please, Sign In to add comment