TOC

This article is currently in the process of being translated into Polish (~37% done).

Klasy:

Właściwości

W poprzednim artykule omawialiśmy pola. Można je porównać do globalnych zmiennych dla danej klasy, które są dostępne dla wszystkich jej metod. Oprócz tego wspomnieliśmy o tym, że inne klasy również mogą mieć do nich dostęp, jeżeli pola te są określone jako public (publiczne), ale takie rozwiązanie zwykle nie jest zalecane. Jeżeli chcesz, aby dostęp do zmiennych/pól był możliwy spoza twojej klasy, powinieneś zamiast tego użyć właściwości.

Kiedy zadeklarujesz pole jako public, zezwalasz na całkowity dostęp do niego z zewnątrz - inne klasy mogą robić z nim, co tylko im się podoba, nawet bez powiadomienia o tym deklarowanej klasy. Właściwości dają nieco kontroli deklarowanej klasie przez możliwość sprecyzowania, czy pole ma być tylko do odczytu lub zapisu oraz możliwość sprawdzania poprawności oraz manipulacji wprowadzanymi danymi, zanim zostaną one zwrócone albo przypisane do pola.

Właściwości wyglądają jak połączenie pola i metody - są one deklarowane tak jak pola, za pomocą widoczności, typu danych i nazwy, ale mają także treść (body) jak metoda, pozwalającą na kontrolowanie jej przeznaczenia:

public string Name
{
	get { return _name; }
	set { _name = value; }
}

Zwróć uwagę na specjalne słowa kluczowe: get oraz set. Używane są one jedynie we właściwościach, by móc kontrolować odczyt (get'ing) i zapis (set'ing) pola. Możesz tworzyć pola, używając tylko samego get LUB set, co sprawi, że dane pole będzie przeznaczone jedynie do zapisu bądź jedynie do odczytu. Możesz także kontrolować widoczność implementacji get lub set, by dla przykładu stworzyć właściwość, która może być odczytana z zewnątrz (public), ale zmodyfikowana wyłącznie z wewnątrz deklarowanej klasy (private).

Możesz też zauważyć, że odwołaliśmy się do pola nazwanego _name. Musi być ono wcześniej zadeklarowane w klasie, by właściwość mogła z niego prawidłowo skorzystać. Przykładowy wzór deklaracji pól z właściwościami wygląda tak:

private string _name = "John Doe";

public string Name
{
	get { return _name; }
	set { _name = value; }
}

Teraz widzisz jak pola i właściwości działają razem: Metoda get zwraca wartość pola _name, podczas gdy metoda set przypisuje do pola _name podaną wartość. W metodzie set używa się specjalnego słowa kluczowego value, które w tym przypadku definiuje wartość przypisaną właściwości.

So, this is pretty much as basic as it gets and at this point, we don't do anything that couldn't be accomplished with a simple public field. But at a later point, you may decide that you want to take more control of how other classes can work with the name and since you have implemented this as a property, you are free to modify the implementation without disturbing anyone using your class. For instance, the Name property could be modified to look like this:

private string _name = "John Doe";

public string Name
{
	get 
	{
		return _name.ToUpper();
	}
	set 
	{
		if(!value.Contains(" "))
			throw new Exception("Please specify both first and last name!");
		_name = value; 
	}
}

The get method now enforces that the value returned is always in UPPERCASE, no matter which case the backing field (_name) is in. In the set method, we have added a couple of lines of code to check whether the passed value contains a space, because we have decided that the name should always consist of both a first and a last name - if this is not the case, an exception is thrown. This is all very crude and simplified, but it should illustrate the full level of control you get when using properties.

Auto-implemented properties

In some cases, you don't need all the control over a field and it can feel cumbersome to implement both a field and a property with the get and set methods not doing anything besides what we saw in the first example. You may be tempted to simply declare your variable as a public field to avoid all this extra hassle. But don't do that! Fortunately for all of us, Microsoft decided to add auto-implemented properties in C# version 3, which will save you several lines of code. Just consider the difference:

Regular property with a declared backing field:

private string _name;

public string Name
{
	get { return _name; }
	set { _name = value; }
}

The exact same behavior, but with an auto-implemented property:

public string Name { get; set; }

Notice that the get and set methods are empty and that no private backing field is declared - in other words, we can now accomplish the exact same behavior as in the first example but with a single line of code! Bear in mind that the private backing field will still exist at runtime - it will be auto-implemented by the compiler, as the name implies. Should you later decide that you need more control of this specific property, you can simply change it to a regular field/property combination with the desired implementation of the get and set methods.

Notice that you are still left with an important mechanism of control from regular properties when using auto-implemented properties: You can leave out the set keyword to create a read-only property, e.g. like this:

public string ReadOnlyProperty { get; }

Write-only properties are not allowed when using auto-implemented properties.

Auto-implemented properties with default values

Prior to C# version 6, you could not define a default value for an auto-implemented property - for that, you would need a declared backing field, which would allow you to initialize the variable with a value:

private string _name = "John Doe";

public string Name
{
	get { return _name; }
	set { _name = value; }
}

But in C# version 6, Microsoft finally added the ability to initialize an auto-implemented property with a default value, like this:

public string Name { get; set; } = "John Doe";

Summary

Properties gives your classes more control over how fields can be accessed and manipulated, and they should always be used when you want to give access to fields from outside of the declaring class.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!