Différence entre la propriété et le champ en C # 3.0+

je me rends compte qu'il semble être un duplicata 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, je sais que

  • Je n'utiliserai pas ma classe avec "techniques that only works on properties" et
  • Je n'utiliserai pas de code de validation dans le getter/setter.

Est y a-t-il une différence (à l'exception du style/développement futur), comme un certain type de contrôle dans la configuration 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 que, que la première version nécessite C# 3.0 ou plus et que le compilateur crée les champs privés.)

130
demandé sur Community 2009-03-17 12:35:35

10 réponses

Encapsulation.

dans le deuxième cas vous venez de définir une variable, dans le premier, il y a 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.

Plus ils apparaissent différemment dans Intellisense :)

Edit: mise à Jour pour OPs mise à jour de question - si vous souhaitez ignorer les autres suggestions ici, les autres la raison est que ce n'est tout simplement pas un bon design OO. Et si vous n'avez pas une très bonne raison de le faire, toujours choisir une propriété sur une variable publique / champ.

110
répondu Mark Ingram 2009-03-17 10:32:19

les champs et les propriétés semblent identiques, mais ils ne le sont pas. Les propriétés sont des méthodes et en tant que telles Il y a certaines choses qui ne sont pas supportées pour les propriétés, et certaines choses qui peuvent se produire avec les propriétés mais jamais dans le cas des champs.

Voici une liste de différences:

Les champs
  • peuvent être utilisés comme entrée pour les arguments out/ref . Les propriétés ne peuvent pas.
  • un champ donnera toujours le même résultat lorsqu'il est appelé plusieurs fois (si nous laissons de problèmes avec plusieurs threads). Une propriété comme DateTime.Now n'est pas toujours égale à elle-même.
  • Les propriétés
  • peuvent créer des exceptions - les champs ne feront jamais cela.
  • propriétés peuvent avoir des effets secondaires ou prendre beaucoup de temps à exécuter. Les champs n'ont pas d'effets secondaires et sera toujours aussi vite que possible pour le type donné.
  • propriétés soutenir une accessibilité différente pour des getters/setters - champs ne sont pas (mais les champs peuvent être readonly )
  • Lorsqu'on utilise la réflexion, les propriétés et les champs sont traités comme différents MemberTypes de sorte qu'ils sont situés différemment ( GetFields vs GetProperties par exemple)
  • le compilateur JIT peut traiter l'accès à la propriété très différemment de l'accès sur le terrain. Il peut cependant être compilé en code natif identique, mais la possibilité de différence existe.
147
répondu Brian Rasmussen 2014-12-08 17:25:28

Un couple rapide, des différences évidentes

  1. une propriété peut avoir des mots clés accessor.

    public string MyString { get; private set; }
    
  2. une propriété peut être annulée en descendants.

    public virtual string MyString { get; protected set; }
    
40
répondu Dustin Campbell 2012-07-25 08:26:11

La différence fondamentale est qu'un champ est une position dans la mémoire où les données du type spécifié est stocké. Une propriété représente un ou deux unités de code est exécutée pour récupérer ou définir une valeur du type spécifié. L'utilisation de ces méthodes d'accès est syntaxiquement cachés à l'aide d'un membre qui semble se comporter comme un champ (en ce qu'elle peut apparaître sur l'autre côté d'une opération d'affectation).

13
répondu AnthonyWJones 2011-08-24 15:43:21
Les accesseurs

sont plus que des champs. D'autres ont déjà souligné plusieurs différences importantes, et je vais en ajouter une autre.

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 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 protégeons à la fois la classe Person d'entrer dans un état invalide, ainsi que le l'appelant n'a rien reçu de la propriété non assignée.

mais nous pourrions pousser la conception encore plus loin. Par exemple, interface pourrait ne pas traiter avec le setter. Il est tout à fait légitime de dire que les consommateurs de IPerson interface sont seulement intéressés à obtenir la propriété, pas à la définir:

interface IPerson
{
    string FirstName { get; }
    string LastName { get; }
}

l'implémentation précédente de la classe Person satisfait cette interface. Le fait qu'il permet à l'appelant également définir la les propriétés n'ont pas de sens du point de vue des consommateurs (qui consomment IPerson ). Les fonctionnalités supplémentaires de la mise en œuvre concrète sont prises en compte par exemple par 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 les promoteurs immobiliers - ce n'est pas son affaire de le savoir. Le consommateur n'a besoin que de getters, et il obtient getters de l'interface, c'est-à-dire du contrat.

un autre complètement valide la mise en œuvre de IPerson serait une classe de personnes immuable et une usine 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 ce code échantillon consommateur une fois de plus n'a pas connaissance de remplir les propriétés. Le consommateur ne s'occupe que des getters et de la mise en œuvre concrète (et de la logique commerciale derrière elle, comme les tests si le nom est vide) est laissée aux classes spécialisées - constructeurs et usines. Toutes ces opérations sont totalement impossibles avec fields.

10
répondu Zoran Horvat 2013-12-24 12:12:03

le premier:

public string MyString {get; set; }

est une propriété; la deuxième, public string MyString ) indique un champ.

la différence est que certaines techniques (ASP.NET databinding for instances), ne fonctionne 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
répondu Frederik Gheysels 2009-03-17 09:38:41

propriétés et champs peuvent, dans de nombreux cas, sembler similaires, mais ils ne le sont pas. Il y a des limites aux propriétés qui n'existent pas pour les champs, et vice versa.

Comme d'autres l'ont mentionné. Vous pouvez faire une propriété en lecture seule ou en écriture seule en rendant l'accesseur privé. Vous ne pouvez pas faire cela avec un champ. Les propriétés peuvent aussi être virtuelles, tandis que les champs ne le peuvent pas.

pense aux propriétés comme du sucre syntaxique pour les fonctions getXXX()/setXXX (). C'est ainsi qu'elles sont mises en œuvre en coulisse.

3
répondu Erik Funkenbusch 2009-03-17 10:09:53

Il y a une autre différence importante entre les champs et les propriétés.

lorsque vous utilisez WPF, vous ne pouvez vous lier qu'aux propriétés publiques. Liant à un domaine public ne fonctionnera pas . Cela est vrai même si vous ne mettez pas en œuvre INotifyPropertyChanged (même si vous devriez toujours).

1
répondu BradleyDotNET 2014-05-07 18:38:29

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 que vous avez besoin de changer OnChange en field comme ceci:

public event Action OnChange = delegate {};

dans une telle situation, nous protégeons notre domaine contre les accès indésirables ou de la modification.

1
répondu maytham-ɯɐɥʇʎɐɯ 2018-01-27 23:20:26

vous devez toujours utiliser propriétés au lieu de champs pour tous les champs publics.Cela garantit que votre bibliothèque a la capacité de mettre en œuvre l'encapsulation pour n'importe quel champ si nécessaire à l'avenir sans briser les codes existants.Si vous remplacez les champs par des propriétés dans les bibliothèques existantes, alors tous les modules dépendants utilisant votre bibliothèque doivent aussi être reconstruits.

0
répondu user1849310 2014-08-09 15:32:33