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

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; }
        }
    }
0

Tworzy sam prywatną zmienną age?

Tak.

Czy powyższy zapis to to samo co:

Tak.

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.

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.

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

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.

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.

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