gettery i settery

0

Przybyłem od Javy i mam takie pytanie. Jeżeli chcę mieć sytuację którą w Javie załatwiłbym tak:

private int num;
public int getNum() {return num}
public void setNum(int num) {this.num = num}

Czyli proste pole i najprostszy getter i setter. To jak mam to samo napisać w C#? Chodzi mi tak naprawdę o to jaki sens jest w pisaniu czegoś takiego co często widzę czyli:

public int num {get; set;}

Bo przecież skoro getter i setter jest publiczny a dostęp do nich odbywa się przez tę samą nazwę co zmienna to przecież równie dobrze mogę olać gettery i dać:

public int num;
0

Oczywiście że możesz ominąć - W Javie tez mogłeś. Setter i getter maja sens tylko wtedy gdy oprócz prostego przypisania wartości do zmiennej chcesz coś jeszcze zrobić

0

Oczywiście wiem że get i set są opcjonalne.

Pytam czym różnią się te dwa zapisy:

public int num {get; set;}

public int num;
Bo często widzę pierwszy, a wydaje mi się że nie ma między nimi różnicy, jest natomiast więcej klikania w pierwszym przypadku.

0

No są różnice, chociażby jeśli używasz reflection, data binding, poza tym tylko w property możesz założyć breakpointa na zmianę wartości zmiennej więc użycie nawet pustych setterów/getterów ułatwia debubbowanie

0

Właśnie o takie naprowadzenie mi chodziło. Poziękował.

1

To ja się jeszcze dopiszę :)

(jeszcze taki mały OT przed postem - za chwilę pewnie wpadnie tu quetz który jest wielkim przeciwnikiem propetry {get;set;} i wyprowadzi mnie w brutalny sposób z błędu posiadania innej opinii (żartuję, oczywiście) ;). Tak czy inaczej... )

Na pierwszy rzut oka

int Count;

i

int Count {get; set;}

wyglądają podobnie. Na drugi zresztą też, bo odwoływanie do obydwóch jest takie same, czyli

int i = Count;
Count = i;

Tak naprawdę jednak property (czyli te gettery i settery) mają za zadanie symulować konstrukcje znane np. z C++

private:
    int count;
public:
    int getCount() { return count; }
    void setCount(int value) { count = value; }

Ok, wracamy do C#. I rzeczywiście - na poziomie kodu "maszynowego" (czyli w przypadku C# oczywiście kodu pośredniego) zwykła zmienna zostanie zapisana po prostu (oczywiście to taka przenośnia, bo nie zamierzam ani siebie ani kogokolwiek katować IL-em ;) )

int Count;

co innego jeśli użyjemy właściwości. zapis int Count {get; set;} da nam w wyniku skądinąd znajomą konstrukcję... (edit: literówki)

private int Count; // ?
public int get_Count();
public int set_Count(int value);

(ten pytajnik to dlatego że ta zmienna musi być, ale nie mam pojęcia gdzie).

I w rzeczywistości odwołanie się do zmiennej również jest intuicyjne - czyli zmienna Count = 10; da nam to samo w kodzie wynikowym, gdz tymczasem i = property Count; da w wyniku i = get_Count(); Nie musisz mi wierzyć na słowo, dodaj do dowolnego swojego kodu deklarację funkcji z przedrostkiem get_ tak żeby kolidowała z nazwą właściwości a otrzymasz błąd kompilacji (Type (typ)' already reserves a member called 'get_(nazwa property)' with the same parameter types)

Jak wiadomo właściwości (czyli jakiekolwiek reagowanie na zmianę / pobranie zmiennej) są jednak czasami potrzebne. W niewielkim projekcie zmienienie zmiennej w właściwość nie powinno być trudne (po prostu wystarczy dopisać {get;set;}) - ale w sporym projekcie może być gorzej, jeśli np. zmienna w jednej klasie zostanie zmieniona we właściwość to wszystkie pozostałe biblioteki korzystające z tej klasy będą musiały być ponownie skompilowane (bo nie znajdą zmiennej nazwanej - zostawmy już to hipotetyczne - Count, a nic ich nie będzie obchodzić metoda get_Count(). ).
Dlatego właśnie dobrym zwyczajem jest też izolowanie pól klasy od świata zewnętrznego.

Ok, kończę już bo za chwilę długość tego posta zacznie dochodzić do średniej bświerczynskiego.
Mam nadzieję że nie napisałem nigdzie jakichś bzdur (marzenia), pozdrawiam...

0

Zmienna oczywiście będzie stworzona, ale nie będzie się nazywała Count, a jakoś tak <cośtam>Count lub coś podobnego, w każdym razie z użyciem < i >. W c# się nie skompiluje, ale w ILu jest to już poprawna nazwa pola i wszystko będzie śmigać, a przy okazji nie będzie problemów z konfliktami nazw :)

0

property{get;set;} powinno się stosować w ramach przyjętej konwencji. Nawet łatwiej jest przejrzeć klasę z metodami/właściwościami niż metodami/polami. Może za bardzo się przyzwyczaiłem do .Net ale przykładowo teraz pisze sporo w javie i drażni mnie chwilami get/set i pole, zamiast właściwości.

Dalej, property nas nie ogranicza ponieważ rozwijając taki get można (tak samo jak w metodzie) , zapobiec 'nie-spójności klasy' czyli przykładowo pobrania typu referencyjnego przez get i ustawienia czegoś innego, pomimo że set jest private/protected

1

Zrobiłem z tego arta, szkoda żeby się to wszystko zmarnowało (@pako - nie znalazłem jak się w końcu nazywają te pola od automatycznie generowanych właściwości, szkoda. Ale dzięki, nie miałem pojęcia o takim tricku)

0

ze jeszcze wspomne ze nie uzywajac wlasciwosci nie da sie zaimplementowac pewnych mechanizmow, ot np. INotifyPropertyChanged i INotifyPropertyChanging

0

@msm - też się ostatnio dowiedziałem o tym. A dokładniej wygląda to tak:

public int Property { get; set; }

jest tłumaczone na:

[CompilerGenerated]
private int <Property>k_BackingField;

public int Property
{
    get
    {
         return this.<Property>k_BackingField;
    }

    set
    {
        this.<Property>k_BackingField = value;
    }
}

Wiedza zaczerpnięta z książki Essential LINQ, Charlie Calvert i Dinesh Kulkarni.

E:
w arcie napisałeś też, że automatyczne propertisy są dostępne od .NET 2.0. Po prawdzie to wersja .NETa chyba nie ma tu większego znaczenia, a atumatic properties (czy jak je MS nazywa, auto-implemented properties) są dostępne od C# 3.0.

0
pako1337 napisał(a)

Po prawdzie to wersja .NETa chyba nie ma tu większego znaczenia,

W pewnym sensie ma, bo kompilator C# 3.0 jest częścią .NET 3.5/VS 2008.

Ale tę pomyłkę trzeba poprawić, w czasach .NET 2.0 tak pisać się nie dało. ;]

1

Poprawiłem. A byłem pewien że od 2.0...

PS. nie spodziewałem się że ktokolwiek przeczyta ten artykuł, więc można powiedzieć że mnie zaskoczyliście ;)

@down - [rotfl]

0

Bez przesady, ja nie czytałem, po prostu ufam pako1337. ;p

0

A ja nie przepuszczę okazji, żeby bliźniemu bład wytknać ;P
Nie no, pomyślałem: zerknę, co mi szkodzi, a nuż się czegoś dowiem, o czym nie wiedziałem. Ale jednak nie ;)
Cóż, ku chwale 4P czy jakoś tak :P

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