web-dev-qa-db-fra.com

Différence entre Property et Field en C # 3.0+

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

  • Je n'utiliserai pas ma classe avec des "techniques qui ne fonctionnent que sur les propriétés" et
  • Je n'utiliserai pas le code de validation dans le getter/setter.

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.)

137
p4bl0

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.

115
Mark Ingram

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:

  • Les champs peuvent être utilisés comme entrée pour out/ref arguments. Les propriétés ne peuvent pas.
  • Un champ produira toujours le même résultat lorsqu'il est appelé plusieurs fois (si nous omettons les problèmes liés à plusieurs threads). Une propriété telle que DateTime.Now n'est pas toujours égal à lui-même.
  • Les propriétés peuvent générer des exceptions - les champs ne le feront jamais.
  • Les propriétés peuvent avoir des effets secondaires ou prendre beaucoup de temps à s'exécuter. Les champs n'ont pas d'effets secondaires et seront toujours aussi rapides que l'on peut s'y attendre pour le type donné.
  • Les propriétés supportent une accessibilité différente pour les getters/setters - les champs ne le sont pas (mais les champs peuvent être créés readonly)
  • Lors de l'utilisation de la réflexion, les propriétés et les champs sont traités de manière différente MemberTypes afin qu'ils soient situés différemment (GetFields vs GetProperties par exemple)
  • Le compilateur JIT peut traiter l’accès aux propriétés de manière très différente de l’accès aux champs. Il peut cependant être compilé en code natif identique mais la différence est là.
154
Brian Rasmussen

Quelques différences rapides et évidentes

  1. Une propriété peut avoir des mots-clés d'accès.

    public string MyString { get; private set; }
    
  2. Une propriété peut être remplacée par des descendants.

    public virtual string MyString { get; protected set; }
    
41
Dustin Campbell

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).

14
AnthonyWJones

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.

11
Zoran Horvat

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.

7
Frederik Gheysels

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.

3
Erik Funkenbusch

Parmi d'autres réponses et exemples, je pense que cet exemple est utile dans certaines situations.

Par exemple, disons que vous avez un OnChangeproperty 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.

1

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).

1
BradleyDotNET

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.

0
user1849310