Jak to jest z właściwością get i set

Odpowiedz Nowy wątek
arekol2
2014-03-30 12:54
arekol2
0

Ostatnio spotkałem się z czymś takim:

class Employee
    {

        public int Age
        { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Employee john = new Employee();
            john.Age = 10;
            Console.WriteLine(john.Age);
        }

    }

Pytanie gdzie kompilator zapisuje dane o wieku? Tworzy sam prywatną zmienną age?
Czy powyższy zapis to to samo co:

class Employee
    {
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }
    }

Pozostało 580 znaków

2014-03-30 12:59

Rejestracja: 7 lat temu

Ostatnio: 1 dzień temu

0

Tworzy sam prywatną zmienną age?

Tak.

Czy powyższy zapis to to samo co:

Tak.

edytowany 1x, ostatnio: n0name_l, 2014-03-30 13:00
A nie publiczną ? "public int Age" - wedlock 2014-03-31 08:27

Pozostało 580 znaków

2014-03-31 10:33

Rejestracja: 7 lat temu

Ostatnio: 1 dzień temu

0

A nie publiczną ? "public int Age"

Nie pytaj sie o rzeczy na temat w komentarzach.

Dla czegos takiego:

public int Foo { get; set; }

Kompilator sobie stworzy prywatna zmienna i dwie metody dostepowe, ktore beda publiczne.

Pozostało 580 znaków

2014-03-31 12:26

Rejestracja: 5 lat temu

Ostatnio: 5 lat temu

0
n0name_l napisał(a):

Czy powyższy zapis to to samo co:

Tak.

NIE.
Używalnośc może być podobna, ale w tle działa to zupełnie inaczej. Properties muszą być inicjalizowane w przeciwieństwie do zwykłych zmiennych.

Jakich zwykłych zmiennych? Pytanie dotyczy zwykłych i automatycznych właściwości. Właściwość automatyczna polega na tym, że kompilator sam wygeneruje pole, które opakowuje, więc programista może pisać mniej kodu. Jeśli twierdzisz, że jest inaczej, to udowodnij to lepiej, najlepiej jakimś ILem. - somekind 2014-03-31 12:49
tak jest, ale to nie znaczy "to samo co", bo kompilator nie tworzy dosłownie pola private int age kiedy widzi właściwość public int Age. tworzy pole ukryte (coś bardziej niż private) do którego nie mamy bezpośredniego dostępu - a tylko przez właściwość. - Azarien 2014-03-31 13:44
Tworzy pole private int jedynie jego nazwa jest inna oraz udekorowane jest atrybutem CompilerGeneratedAttribute. Nie ma oczywiście do niego dostępu z poziomu kodu źródłowego, bo nie ma go w nim - to chyba oczywiste. - somekind 2014-03-31 14:02

Pozostało 580 znaków

2014-03-31 15:39

Rejestracja: 7 lat temu

Ostatnio: 1 dzień temu

2

ale w tle działa to zupełnie inaczej.

Ok, get/set dla zwyklych wlasciwosci:

    .method public hidebysig specialname 
           instance default int32 get_Age1 ()  cil managed 
    {
        // Method begins at RVA 0x2050
    // Code size 7 (0x7)
    .maxstack 8
    IL_0000:  ldarg.0 
    IL_0001:  ldfld int32 Person::_age1
    IL_0006:  ret 
    } // end of method Person::get_Age1

    // method line 2
    .method public hidebysig specialname 
           instance default void set_Age1 (int32 'value')  cil managed 
    {
        // Method begins at RVA 0x2058
    // Code size 8 (0x8)
    .maxstack 8
    IL_0000:  ldarg.0 
    IL_0001:  ldarg.1 
    IL_0002:  stfld int32 Person::_age1
    IL_0007:  ret 
    } // end of method Person::set_Age1

Dla automatycznych:

    .method public hidebysig specialname 
           instance default int32 get_Age2 ()  cil managed 
    {
        .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x2061
    // Code size 7 (0x7)
    .maxstack 8
    IL_0000:  ldarg.0 
    IL_0001:  ldfld int32 Person::'<Age2>k__BackingField'
    IL_0006:  ret 
    } // end of method Person::get_Age2

    // method line 4
    .method public hidebysig specialname 
           instance default void set_Age2 (int32 'value')  cil managed 
    {
        .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x2069
    // Code size 8 (0x8)
    .maxstack 8
    IL_0000:  ldarg.0 
    IL_0001:  ldarg.1 
    IL_0002:  stfld int32 Person::'<Age2>k__BackingField'
    IL_0007:  ret 
    } // end of method Person::set_Age2

W dzialaniu obu metod nie ma zadnej roznicy, poza tym, ze automatycznie maja zrozumialy atrybut.

Properties muszą być inicjalizowane w przeciwieństwie do zwykłych zmiennych.

Przez kogo musza byc inicjalizowane? https://ideone.com/6PE9fv

edytowany 1x, ostatnio: n0name_l, 2014-03-31 15:39

Pozostało 580 znaków

2014-03-31 18:26

Rejestracja: 16 lat temu

Ostatnio: 1 dzień temu

2

To ja jeszcze pokażę, jak to jest realizowane na poziomie kodu maszynowego, po przejściu przez JIT:

    class Employee
    {
        public int Prop { get; set; }
        public int Field;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Employee john = new Employee();
            john.Prop = 42;
            Console.WriteLine(john.Prop);
            john.Field = 42;
            Console.WriteLine(john.Field);
        }
    }
            john.Prop = 42;
006528CF C7 46 08 2A 00 00 00 mov         dword ptr [esi+8],2Ah  

            john.Field = 42;
006528F6 C7 46 04 2A 00 00 00 mov         dword ptr [esi+4],2Ah  

Ta daaam! Nie ma znaczenia, czy mamy właściwość czy pole, kompilator i tak ostatecznie przerobi kod tak, jakby to było zwykłe, publiczne pole.

edytowany 1x, ostatnio: Azarien, 2014-03-31 18:27
JIT czy AOT? - Wibowit 2014-03-31 20:10
raczej to pierwsze, debugowałem proces, nie dezasemblowałem exeka z ngen-a. - Azarien 2014-03-31 21:40
jak mogę odpalić swój program aby zobaczyć kod maszynowy? - ne0 2014-04-01 15:12

Pozostało 580 znaków

2014-04-01 16:05

Rejestracja: 16 lat temu

Ostatnio: 1 dzień temu

0

jak mogę odpalić swój program aby zobaczyć kod maszynowy?

Pod Visual Studio.

Po pierwsze, bardziej nas raczej interesuje kod zoptymalizowany - więc będziemy debugować build Release.
Po drugie, w opcjach VS, w zakładce Debugger, trzeba wyłączyć opcję „suppress JIT optimization on module load”, czy jakoś tak.
Ustawiamy breakpointa wewnątrz funkcji, którą chcemy zobaczyć. Odpalamy program.
Gdy program się zatrzyma, otwieramy okno Disassembly.

Zadanie domowe: porównać kod wersji Release z wersją Debug.

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0