Ustawianie właściwości w klasie

0

Zastanawiam się jak najlepiej ustawiac właściwości klasy
czy lepiej zrobić:

public class Osoba
{
	private string imie;
	private string nazwisko;
	
	public string Imie
	{
		get{return imie;}
		set
		{ 
			if(!string.IsNullOrEmpty(value))
				imie=value;
			else
				imie="XXXXXXX";
		}
	}
	
	public string Nazwisko
	{
		get{return nazwisko;}
		set
		{ 
			if(!string.IsNullOrEmpty(value))
				nazwisko=value;
			else
				nazwisko="XXXXXXX";
		}
	}
}

czy

public class Osoba
{
	public string Imie
	{
		get;
		private set;
	}
	
	public string Nazwisko
	{
		get;
		private set;
	}
	
	public void SetImie(string imie)
	{
		if(!string.IsNullOrEmpty(imie))
				Imie=imie;
			else
				Imie="XXXXXXX";
	}
	
	public void SetNazwisko(string nazwisko)
	{
		if(!string.IsNullOrEmpty(nazwisko))
				Nazwisko=nazwisko;
			else
				Nazwisko="XXXXXXX";
	}
}

Który sposób jest preferowany i dlaczego?

1

Preferowane byłoby ustawianie ich przez konstruktor i niemutowanie obiektu:


public sealed class Osoba
{
   public string Imie { get; }
   public string Nazwisko {get; }
    
   public Osoba(string imie, string nazwisko) 
   {
       Imie = imie;
       Nazwisko = nazwisko;
   }
}

Wybór rozwiązania zależy jednak od kontekstu. Czasami trzeba użyć publicznych setterów, np. przy bindingu w WPF albo deserializacji, jeśli biblioteka nie pozwala na użycie konstruktora.
Dla trywialnych klas, jak modele do bindowania we wspomnianym WPF, wystarczy więc zwykły setter. Dla złożonej logiki preferowane może być zwracanie nowego obiektu zamiast mutowania, coś w tym rodzaju:

public Osoba SetImie(string imie) 
{
  return new Osoba(imie, Nazwisko);
}
2

Sposób drugi nie ma żadnego sensu, nie po to język oferuje właściwości, aby pisać dodatkowe metody.
A najlepiej to w ogóle tak zrobić:

public class Osoba
{
    private string Imie { get; }
    private string Nazwisko { get; }

   public Osoba(string imie = "XXXXX", string nazwisko = "XXXXX")
   {
      this.Imie = imie;
      this.Osoba = osoba;
   }
}
0

@SkrzydlatyWąż, @somekind : czyli rozumiem, ze jakieś sprawdzania robić we właściwości, a najlepiej użyć parametrów domyślnych konstruktora. Co jeśli będę potrzebował ustawić np. 20 parametrów, wtedy ustawianie przez konstruktor robi się niewygodne?

0

Dlaczego przy 20 właściwościach ustawianie przez konstruktor jest niewygodne, a przez właściwości wygodne?
Moim zdaniem przy 20 właściwościach wszystko jest niewygodne.

0

Factories, Builders, Fluent interfaces...

var fireItem = new FireItemBuilder()
					.inIndustry("Building Construction")
					.withOccupation("Workshop")
					.InAreaWithPostalCode(7800)
					.forSumInsured(200000.00)
					.havingRoofing("Non-Standard")
					.create();					
0
somekind napisał(a):

Dlaczego przy 20 właściwościach ustawianie przez konstruktor jest niewygodne, a przez właściwości wygodne?
Moim zdaniem przy 20 właściwościach wszystko jest niewygodne.

To jak organizowac klasy ktore potrzebuja miec większą ilość właściwości?

WeiXiao napisał(a):

Factories, Builders, Fluent interfaces...

var fireItem = new FireItemBuilder()
					.inIndustry("Building Construction")
					.withOccupation("Workshop")
					.InAreaWithPostalCode(7800)
					.forSumInsured(200000.00)
					.havingRoofing("Non-Standard")
					.create();					

Co to jest? Ciekawie wygląda.

0

Zamiast tworzyć obiekt bezpośrednio przez konstruktor, to stosujesz inną klasę - "budowniczy" czy "fabryka" czy cokolwiek innego i jakkolwiek to zwał, która stworzy ten obiekt.

Zalety mogą być takie, że ta osobna klasa będzie gwarantować poprawność danych i/lub ułatwi tworzenie tego obiektu np. stosując takie wymowne metody.

Jeżeli skorzystasz z czegoś co nazywa się fluent API, to wyjdzie Ci takie ładne składanie metod (method chaining) jak np. LINQ.

Pierwsze przykład z Googla

https://kamiljozwiak.net/fluent-api/

https://devstyle.pl/2010/07/15/tworzenie-obiektow-poprzez-fluent-interface-dla-kazdego/

0
kalimata napisał(a):

To jak organizowac klasy ktore potrzebuja miec większą ilość właściwości?

To nie jest odpowiedź na moje pytanie. :P

Skoro musisz gdzieś przekazać 20 wartości, to moim zdaniem równie upierdliwie sjest robić to przez konstruktor jak i przez właściwości.
Pytanie, co to za obiekt, który ma tyle właściwości?
Jeśli logika biznesowa, to albo coś jest nie tak z obiektem, a jeśli nie, to można to ogarnąć buiderem czy innym factory, jak to @WeiXiao pokazał.
Jeśli jednak to odpada z jakichś względów i jest sens, aby obiekt był mutowalny, to można mieć jakaś walidację we właściwościach.
Jeśli to jakieś DTO czy inna struktura danych, to prościej chyba mieć proste setery + fabrykę albo walidator niż logikę we właściwościach.

0

@WeiXiao, @somekind: potrzebuje zbudowac klasę do obslugi faktury oraz jej elementow a na takiej fakturze jest sporo wlasciwosci do wypelnienia. Do tego osobna klasa na pozycje faktury ktora tez bedzie miala troche wlasciwosci. Szukam jakiegos dobrego sposobu zaprojektowania tego.

0

Ustawianie obiektu przez same właściwości to także ryzyko, że jakiemuś śmieszkowi przyjdzie do głowy coś takiego:

var osoba = new Osoba() 
{
   Imie = "Janusz
};

Wtedy walidacja na inne właściwości nawet nie zadziała, a nulle przejdą dalej, chyba że zastosujesz domyślne wartości właściwości.

Skoro klasa ma 20 właściwości, to może lepiej skomponować ją z mniejszych klas, zamiast trzymać wszystkie wartości w jednej?

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