Je me rends compte que cela semble être une copie de Quelle est la différence entre un champ et une propriété en C #? mais ma question a une légère différence (de mon point de vue):
Une fois que je sais que
Existe-t-il une différence (à l'exception des styles et des développements futurs), comme un type de contrôle dans la définition de la propriété?
Y a-t-il une différence supplémentaire entre:
public string MyString { get; set; }
et
public string myString;
(Je suis conscient du fait que la première version nécessite C # 3.0 ou supérieur et que le compilateur crée les champs privés.)
Encapsulation.
Dans le second cas, vous venez de définir une variable, dans le premier, il existe un getter/setter autour de la variable. Donc, si vous décidez de valider la variable à une date ultérieure, ce sera beaucoup plus facile.
De plus, ils apparaissent différemment dans Intellisense :)
Edit: Mise à jour pour la question mise à jour des PO - si vous voulez ignorer les autres suggestions ici, l’autre raison est que ce n’est tout simplement pas bon OO conception. Et si vous N'ayez pas une très bonne raison de le faire, toujours choisissez une propriété sur une variable/un champ public.
Les champs et les propriétés se ressemblent, mais ils ne le sont pas. Les propriétés sont des méthodes et, en tant que telles, certaines choses ne sont pas prises en charge pour les propriétés, et certaines choses peuvent arriver avec des propriétés mais jamais dans le cas de champs.
Voici une liste de différences:
out/ref
arguments. Les propriétés ne peuvent pas.DateTime.Now
n'est pas toujours égal à lui-même.readonly
)MemberTypes
afin qu'ils soient situés différemment (GetFields
vs GetProperties
par exemple)Quelques différences rapides et évidentes
Une propriété peut avoir des mots-clés d'accès.
public string MyString { get; private set; }
Une propriété peut être remplacée par des descendants.
public virtual string MyString { get; protected set; }
La différence fondamentale est qu'un champ est une position en mémoire où des données du type spécifié sont stockées. Une propriété représente une ou deux unités de code exécutées pour extraire ou définir une valeur du type spécifié. L'utilisation de ces méthodes d'accès est syntaxiquement masquée à l'aide d'un membre qui semble se comporter comme un champ (en ce sens qu'il peut apparaître de part et d'autre d'une opération d'affectation).
Les accesseurs sont plus que des champs. D'autres ont déjà souligné plusieurs différences importantes, et je vais en ajouter une de plus.
Les propriétés participent aux classes d'interface. Par exemple:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
Cette interface peut être satisfaite de plusieurs manières. 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 empêchons la classe Person
d'entrer dans un état non valide, ainsi que l'appelant de récupérer la valeur null à partir de la propriété non attribuée.
Mais nous pourrions pousser la conception encore plus loin. Par exemple, l'interface peut ne pas traiter avec le passeur. Il est tout à fait légitime de dire que les utilisateurs de IPerson
interface ne sont intéressés que par l'obtention de la propriété, et non par sa configuration:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
La précédente implémentation de la classe Person
satisfait cette interface. Le fait de laisser l'appelant définir également les propriétés n'a pas de sens du point de vue des consommateurs (qui consomment IPerson
). Les fonctionnalités supplémentaires de l'implémentation concrète sont prises en compte par le constructeur, par exemple:
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 les utilisateurs de propriété - ce n’est pas son affaire de le savoir. Le consommateur n’a besoin que d’obstacles et il obtient l’interface, c’est-à-dire le contrat.
Une autre implémentation complètement valide de IPerson
serait une classe de personnes immuable et une fabrique de personnes correspondante:
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, le consommateur n'a encore aucune connaissance sur le remplissage des propriétés. Consumer traite uniquement des accesseurs et une implémentation concrète (et la logique métier qui la sous-tend, telle que tester si name est vide) est laissée aux classes spécialisées - constructeurs et usines. Toutes ces opérations sont absolument impossibles avec des champs.
Le premier:
public string MyString {get; set; }
est une propriété; le deuxième ( public string MyString
) désigne un champ.
La différence est que certaines techniques (liaison de données ASP.NET pour les instances) ne fonctionnent que sur les propriétés et non sur les champs. Il en va de même pour la sérialisation XML: seules les propriétés sont sérialisées, les champs ne sont pas sérialisés.
Les propriétés et les champs peuvent, dans de nombreux cas, sembler similaires, mais ils ne le sont pas. Il existe des limitations aux propriétés qui n'existent pas pour les champs, et inversement.
Comme d'autres l'ont mentionné. Vous pouvez rendre une propriété en lecture seule ou en écriture seule en rendant son accesseur privé. Vous ne pouvez pas faire cela avec un champ. Les propriétés peuvent également être virtuelles, contrairement aux champs.
Pensez aux propriétés en tant que sucre syntaxique pour les fonctions getXXX ()/setXXX (). Voici comment ils sont mis en œuvre dans les coulisses.
Parmi d'autres réponses et exemples, je pense que cet exemple est utile dans certaines situations.
Par exemple, disons que vous avez un OnChange
property
comme suit:
public Action OnChange { get; set; }
Si vous voulez utiliser des délégués, vous devez le changer OnChange
en field
comme ceci:
public event Action OnChange = delegate {};
Dans une telle situation, nous protégeons notre domaine des accès non autorisés ou des modifications.
Il existe une autre différence importante entre les champs et les propriétés.
Lorsque vous utilisez WPF, vous pouvez uniquement vous lier à des propriétés publiques. La liaison à un champ public fonctionnera pas. Ceci est vrai même lorsque vous n'implémentez pas INotifyPropertyChanged
(même si vous devriez toujours le faire).
Vous devez toujours utiliser des propriétés plutôt que des champs pour les champs publics. Cela garantit à votre bibliothèque la possibilité d'implémenter l'encapsulation de tout champ si nécessaire à l'avenir sans rompre les codes existants. Si vous remplacez les champs par des propriétés dans des bibliothèques existantes, toutes les les modules dépendants utilisant votre bibliothèque doivent également être reconstruits.