Les accesseurs sont plus que des champs. D'autres l'ont déjà souligné plusieurs différences importantes, et je vais en ajouter un de plus.
Propriétés de prendre part à des classes d'interface. Par exemple:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
Cette interface peut être satisfait de plusieurs façons. Par exemple:
class Person: IPerson
{
private string _name;
public string FirstName
{
get
{
return _name ?? string.Empty;
}
set
{
if (value == null)
throw new System.ArgumentNullException("value");
_name = value;
}
}
...
}
Dans cette implémentation, nous visons à protéger à la fois l' Person
de la classe d'entrer dans un état non valide, ainsi qu'à l'appelant d'obtenir nulle de la non attribuées à la propriété.
Mais on pourrait pousser la conception même de plus loin. Par exemple, l'interface peut ne pas traiter avec le setter. Il est tout à fait légitime de dire que les consommateurs de IPerson
interface sont uniquement intéressés par l'obtention de la propriété, et non dans l'établissement:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
Mise en oeuvre préalable de l' Person
classe répond à cette interface. Le fait qu'il permet à l'appelant également définir les propriétés de sens du point de vue des consommateurs (qui consomment IPerson
). Fonctionnalités supplémentaires de la mise en œuvre concrète n'est prise en considération, par exemple, le constructeur:
class PersonBuilder: IPersonBuilder
{
IPerson BuildPerson(IContext context)
{
Person person = new Person();
person.FirstName = context.GetFirstName();
person.LastName = context.GetLastName();
return person;
}
}
...
void Consumer(IPersonBuilder builder, IContext context)
{
IPerson person = builder.BuildPerson(context);
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
Dans ce code, le consommateur ne connaît pas bien les setters - il n'est pas à lui de les connaître. Consommateur doit simplement les méthodes de lecture, et il obtient des getters de l'interface, c'est à dire le contrat.
Un autre tout à fait valable, la mise en œuvre de l' IPerson
serait immuable classe personne et une personne correspondante de l'usine:
class Person: IPerson
{
public Person(string firstName, string lastName)
{
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
throw new System.ArgumentException();
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
}
...
class PersonFactory: IPersonFactory
{
public IPerson CreatePerson(string firstName, string lastName)
{
return new Person(firstName, lastName);
}
}
...
void Consumer(IPersonFactory factory)
{
IPerson person = factory.CreatePerson("John", "Doe");
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
Dans cet exemple de code de consommation, une fois encore, n'a pas connaissance de remplir les propriétés. Les consommateurs ne traite qu'avec les getters et la mise en œuvre concrète (et la logique métier derrière elle, comme un test si le nom est vide) est laissé à des classes spécialisées - les constructeurs et les usines. Toutes ces opérations sont tout à fait impossible avec des champs.