web-dev-qa-db-fra.com

Quelle est la différence entre un champ et une propriété?

En C #, en quoi un champ est-il différent d'une propriété et quand faut-il utiliser un champ à la place d'une propriété?

1001
Anonymous

Les propriétés exposent les champs. Les champs doivent (presque toujours) rester confidentiels pour une classe et accessibles via les propriétés get et set. Les propriétés fournissent un niveau d'abstraction vous permettant de modifier les champs sans affecter la manière externe dont ils accèdent par les choses qui utilisent votre classe.

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty{get;set;} 
}

@Kent souligne que les propriétés ne sont pas obligées d'encapsuler des champs, elles pourraient effectuer un calcul sur d'autres champs ou servir à d'autres fins.

@GSS indique que vous pouvez également utiliser une autre logique, telle que la validation, lors de l'accès à une propriété, autre fonctionnalité utile.

871
Cory

Selon les principes de la programmation orientée objet, le fonctionnement interne d'une classe doit être caché du monde extérieur. Si vous exposez un champ, vous exposez essentiellement l'implémentation interne de la classe. Par conséquent, nous encapsulons les champs avec des propriétés (ou des méthodes dans le cas de Java) pour nous donner la possibilité de modifier l'implémentation sans détruire le code qui dépend de nous. Voir que nous pouvons mettre la logique dans la propriété nous permet également d’exécuter la logique de validation, etc. si nous en avons besoin. C # 3 a la notion éventuellement déroutante d'autoproperties. Cela nous permet de définir simplement la propriété et le compilateur C # 3 générera le champ privé pour nous.

public class Person
{
   private string _name;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }
   public int Age{get;set;} //AutoProperty generates private field for us
}
240
danswain

Une différence importante est que les interfaces peuvent avoir des propriétés mais pas des champs. Ceci, à mon sens, souligne que les propriétés doivent être utilisées pour définir l'interface publique d'une classe, alors que les champs sont destinés à être utilisés dans les rouages ​​internes et privés d'une classe. En règle générale, je crée rarement des champs publics et de la même manière, je crée rarement des propriétés non publiques.

156
Hans Løken

Je vais vous donner quelques exemples d'utilisation de propriétés qui pourraient faire tourner les engrenages:

  • Initialisation différée : Si vous avez la propriété d'un objet qui est coûteuse à charger, mais dont l'accès n'est pas tellement présent dans Pour que le code fonctionne normalement, vous pouvez différer son chargement via la propriété. Ainsi, la première fois qu'un autre module tente d'appeler cette propriété, il vérifie si le champ sous-jacent est nul. Si c'est le cas, il le charge et le charge, à l'insu du module appelant. Cela peut grandement accélérer l’initialisation de l’objet.
  • Dirty Tracking: Ce que j'ai appris de ma propre question ici sur StackOverflow. Lorsque j'ai beaucoup d'objets dont les valeurs peuvent avoir changé au cours d'une analyse, je peux utiliser cette propriété pour déterminer si elles doivent être sauvegardées dans la base de données ou non. Si aucune propriété d'un objet n'a été modifiée, l'indicateur IsDirty ne sera pas déclenché et, par conséquent, la fonctionnalité d'enregistrement l'ignorera lors du choix de ce qui doit revenir à la base de données.
95
Chris

À l'aide de Propriétés, vous pouvez générer un événement lorsque la valeur de la propriété est modifiée (aka. PropertyChangedEvent) ou avant la modification de la valeur pour prendre en charge l'annulation.

Ceci n'est pas possible avec les champs (accès direct).

public class Person {
 private string _name;

 public event EventHandler NameChanging;     
 public event EventHandler NameChanged;

 public string Name{
  get
  {
     return _name;
  }
  set
  {
     OnNameChanging();
     _name = value;
     OnNameChanged();
  }
 }

 private void OnNameChanging(){
   EventHandler localEvent = NameChanging;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }

 private void OnNameChanged(){
   EventHandler localEvent = NameChanged;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }
}
48
Jehof

Comme beaucoup d’entre eux ont expliqué les avantages et inconvénients techniques de Properties et Field, il est temps de passer à des exemples en temps réel.

1. Propriétés vous permet de définir le niveau d'accès en lecture seule

Considérons le cas de dataTable.Rows.Count et dataTable.Columns[i].Caption. Ils viennent de la classe DataTable et les deux sont publics pour nous. La différence dans leur niveau d'accès réside dans le fait que nous ne pouvons pas définir la valeur sur dataTable.Rows.Count mais nous pouvons lire et écrire sur dataTable.Columns[i].Caption. Est-ce possible via Field? Non!!! Cela peut être fait avec Properties uniquement.

public class DataTable
{
    public class Rows
    {       
       private string _count;        

       // This Count will be accessable to us but have used only "get" ie, readonly
       public int Count
       {
           get
           {
              return _count;
           }       
       }
    } 

    public class Columns
    {
        private string _caption;        

        // Used both "get" and "set" ie, readable and writable
        public string Caption
        {
           get
           {
              return _caption;
           }
           set
           {
              _caption = value;
           }
       }       
    } 
}

2. Propriétés dans PropertyGrid

Vous avez peut-être travaillé avec Button dans Visual Studio. Ses propriétés sont montrées dans PropertyGrid comme Text, Name etc. Lorsque nous glissons et déposons un bouton, et lorsque nous cliquons sur les propriétés, il trouve automatiquement la classe Button et filtre Properties et montre que dans PropertyGrid (où PropertyGrid ne s'affiche pas Field même s’ils sont publics).

public class Button
{
    private string _text;        
    private string _name;
    private string _someProperty;

    public string Text
    {
        get
        {
           return _text;
        }
        set
        {
           _text = value;
        }
   } 

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

   [Browsable(false)]
   public string SomeProperty
   {
        get
        {
           return _someProperty;
        }
        set
        {
           _someProperty= value;
        }
   } 

Dans PropertyGrid, les propriétés Name et Text seront affichées, mais pas SomeProperty. Pourquoi??? Parce que les propriétés peuvent accepter Attributes . Il ne s'affiche pas dans le cas où [Browsable(false)] est faux.

3. Peut exécuter des instructions dans les propriétés

public class Rows
{       
    private string _count;        


    public int Count
    {
        get
        {
           return CalculateNoOfRows();
        }  
    } 

    public int CalculateNoOfRows()
    {
         // Calculation here and finally set the value to _count
         return _count;
    }
}

4. Seules les propriétés peuvent être utilisées dans Binding Source

Binding Source nous aide à réduire le nombre de lignes de code. Fields ne sont pas acceptés par BindingSource. Nous devrions utiliser Properties pour cela.

5. Mode de débogage

Considérez que nous utilisons Field pour conserver une valeur. À un moment donné, nous devons déboguer et vérifier où la valeur devient nulle pour ce champ. Ce sera difficile à faire lorsque le nombre de lignes de code est supérieur à 1000. Dans de telles situations, nous pouvons utiliser Property et définir le mode débogage dans Property.

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }
43
Sarath Avanavu

DIFFERENCES - UTILISATIONS (quand et pourquoi)

Un champ est une variable déclarée directement dans une classe ou une structure. Une classe ou une structure peut avoir des champs d'instance ou des champs statiques, ou les deux. En règle générale, vous devez utiliser les champs uniquement pour les variables ayant une accessibilité privée ou protégée . Les données que votre classe expose au code client doivent être fournies via des méthodes, des propriétés et des indexeurs. En utilisant ces constructions pour un accès indirect aux champs internes, vous pouvez vous protéger contre les valeurs d'entrée non valides.

Une propriété est un membre qui fournit un mécanisme flexible pour lire, écrire ou calculer la valeur d'un champ privé. Les propriétés peuvent être utilisées comme si elles étaient des membres de données publiques, mais ce sont en réalité des méthodes spéciales appelées accesseurs . Cela permet d’accéder facilement aux données et contribue toujours à promouvoir la sécurité et la flexibilité des méthodes . Les propriétés permettent à une classe d'exposer un moyen public d'obtenir et de définir des valeurs, tout en masquant le code d'implémentation ou de vérification. Un accesseur de propriété get est utilisé pour renvoyer la valeur de la propriété, et un accesseur set est utilisé pour affecter une nouvelle valeur.

30
makiSTB

Les propriétés ont pour principal avantage de vous permettre de modifier le mode d'accès aux données d'un objet sans casser son interface publique. Par exemple, si vous devez ajouter une validation supplémentaire ou modifier un champ stocké en un champ calculé, vous pouvez le faire facilement si vous avez initialement exposé le champ en tant que propriété. Si vous venez d’exposer directement un champ, vous devrez alors modifier l’interface publique de votre classe pour ajouter la nouvelle fonctionnalité. Ce changement romprait les clients existants en les obligeant à être recompilés avant de pouvoir utiliser la nouvelle version de votre code.

Si vous écrivez une bibliothèque de classes conçue pour une utilisation étendue (comme le .NET Framework, utilisé par des millions de personnes), cela peut poser problème. Cependant, si vous écrivez une classe utilisée en interne dans une petite base de code (disons <= 50 lignes K), ce n'est pas grave, car vos modifications ne toucheraient personne. Dans ce cas, cela dépend vraiment de vos préférences personnelles.

12
Scott Wisniewski

En arrière-plan, une propriété est compilée dans des méthodes. Ainsi, une propriété Name est compilée dans get_Name() et set_Name(string value). Vous pouvez voir cela si vous étudiez le code compilé. Il existe donc une (très) petite surcharge de performances lors de leur utilisation. Normalement, vous utiliserez toujours une propriété si vous exposez un champ à l'extérieur, et vous l'utiliserez souvent en interne si vous devez valider la valeur.

10
Rune Grimstad

Les propriétés prennent en charge l’accès asymétrique, c’est-à-dire que vous pouvez avoir soit un getter et un setter, soit un seul des deux. De même, les propriétés prennent en charge l'accessibilité individuelle pour le getter/setter. Les champs sont toujours symétriques, c’est-à-dire que vous pouvez toujours obtenir et définir la valeur. Une exception à cette règle concerne les champs en lecture seule qui ne peuvent évidemment pas être définis après l'initialisation.

Les propriétés peuvent durer très longtemps, avoir des effets secondaires et même générer des exceptions. Les champs sont rapides, sans effets secondaires et ne jetteront jamais d'exception. En raison d'effets secondaires, une propriété peut renvoyer une valeur différente pour chaque appel (comme cela peut être le cas pour DateTime.Now, c.-à-d. DateTime.Now n'est pas toujours égal à DateTime.Now). Les champs renvoient toujours la même valeur.

Les champs peuvent être utilisés pour les paramètres out/ref, mais pas les propriétés. Les propriétés supportent une logique supplémentaire - ceci pourrait être utilisé pour implémenter un chargement paresseux, entre autres.

Les propriétés supportent un niveau d'abstraction en encapsulant tout ce que cela signifie pour obtenir/définir la valeur.

Utilisez les propriétés dans la plupart/tous les cas, mais essayez d'éviter les effets secondaires.

10
Brian Rasmussen

Lorsque vous souhaitez que votre variable privée (champ) soit accessible à un objet de votre classe à partir d'autres classes, vous devez créer des propriétés pour ces variables.

par exemple, si j'ai des variables nommées "id" et "name" qui sont privées, mais il peut y avoir une situation où cette variable est nécessaire pour une opération de lecture/écriture en dehors de la classe. Dans cette situation, property peut m'aider à obtenir cette variable en lecture/écriture en fonction du get/set défini pour la propriété. Une propriété peut être un readonly/writeonly/readwrite les deux.

voici la démo

class Employee
{
    // Private Fields for Employee
    private int id;
    private string name;

    //Property for id variable/field
    public int EmployeeId
    {
       get
       {
          return id;
       }
       set
       {
          id = value;
       }
    }

    //Property for name variable/field
    public string EmployeeName
    {
       get
       {
          return name;
       }
       set
       {
          name = value;
       }
   }
}

class MyMain
{
    public static void Main(string [] args)
    {
       Employee aEmployee = new Employee();
       aEmployee.EmployeeId = 101;
       aEmployee.EmployeeName = "Sundaran S";
    }
}
7
Petryanu

La deuxième question ici, "quand un champ doit-il être utilisé à la place d'une propriété?", N'est abordée que brièvement dans cette autre réponse et un peu celle-ci aussi , mais pas vraiment beaucoup de détails.

En règle générale, toutes les autres réponses sont pertinentes pour une bonne conception: préférez exposer les propriétés aux champs. Bien que vous ne vous trouviez probablement pas régulièrement en train de vous dire "wow, imaginez à quel point les choses seraient pires si j'avais fait de ce terrain un terrain plutôt qu'une propriété" , il est plus rare de penser à une situation dans laquelle on dirait "wow, dieu merci, j'ai utilisé un champ ici plutôt qu'une propriété."

Mais il y a un avantage que les champs ont sur les propriétés, c'est leur capacité à être utilisés comme paramètres "ref"/"out". Supposons que vous ayez une méthode avec la signature suivante:

public void TransformPoint(ref double x, ref double y);

et supposons que vous souhaitiez utiliser cette méthode pour transformer un tableau créé comme ceci:

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

Voici le moyen le plus rapide de le faire car X et Y sont des propriétés:

for (int i = 0; i < points.Length; i++)
{
    double x = points[i].X;
    double y = points[i].Y;
    TransformPoint(ref x, ref y);
    points[i].X = x;
    points[i].Y = y;
}

Et ça va être très bon! Sauf si vous avez des mesures qui prouvent le contraire, il n'y a aucune raison de jeter une puanteur. Mais je crois qu'il n'est pas techniquement garanti d'être aussi rapide que cela:

internal struct MyPoint
{
    internal double X;
    internal double Y;
}

// ...

MyPoint[] points = new MyPoint[1000000];
Initialize(points);

// ...

for (int i = 0; i < points.Length; i++)
{
    TransformPoint(ref points[i].X, ref points[i].Y);
}

En faisant mesures moi-même, la version avec champs prend environ 61% du temps comme version avec propriétés (.NET 4.6, Windows 7, x64, mode de publication, pas de débogueur attaché). Plus la méthode TransformPoint est chère, moins la différence devient prononcée. Pour le répéter vous-même, lancez avec la première ligne commentée et sans commentaire.

Même si les performances ci-dessus ne présentaient aucun avantage en termes de performances, il peut être avantageux d'utiliser d'autres paramètres tels que les paramètres ref et out, par exemple lorsque vous appelez le Interlocked ou Volatile famille de méthodes. Remarque: si cela est nouveau pour vous, Volatile est fondamentalement un moyen d'obtenir le même comportement que celui fourni par le mot clé volatile. En tant que tel, comme volatile, il ne résout pas comme par magie tous les problèmes liés à la sécurité des threads, comme son nom l'indique.

Je ne veux vraiment pas avoir l’air de suggérer que vous disiez: "Oh, je devrais commencer à exposer des champs au lieu de propriétés." Le fait est que si vous devez utiliser régulièrement ces membres dans des appels qui prennent des paramètres "ref" ou "out", en particulier sur quelque chose qui pourrait être un simple type de valeur qui n'aurait probablement pas besoin des éléments à valeur ajoutée des propriétés, un argument peut être fait.

6
Joe Amenta

Cette page sur MSDN présente une comparaison et des astuces sur lesquelles utiliser lorsque:

https://msdn.Microsoft.com/en-us/library/9d65as2e (v = vs.90) .aspx

4
shivesh suman

Techniquement, je ne pense pas qu'il y ait de différence, car les propriétés ne sont que des wrappers autour de champs créés par l'utilisateur ou automatiquement par le compilateur. Le but de ces propriétés est d'imposer l'encapsuation et d'offrir une fonctionnalité allégée semblable à une méthode. C'est juste une mauvaise pratique de déclarer les champs comme publics, mais cela ne pose aucun problème.

4
Brahim Boulkriat

Si vous allez utiliser des primitives de thread, vous devez utiliser des champs. Les propriétés peuvent casser votre code threadé. En dehors de cela, ce que Cory a dit est correct.

4

(Cela devrait vraiment être un commentaire, mais je ne peux pas poster un commentaire, donc veuillez excuser s'il ne convient pas à un article).

J'ai déjà travaillé à un endroit où la pratique recommandée était d'utiliser des champs publics au lieu de propriétés lorsque la propriété équivalente def venait simplement d'accéder à un champ, comme dans:

get { return _afield; }
set { _afield = value; }

Leur raisonnement était que le champ public pouvait être converti ultérieurement en propriété si nécessaire. Cela me semblait un peu étrange à l'époque. À en juger par ces messages, il semble que peu de gens ici seraient d'accord non plus. Qu'avez-vous pu dire pour essayer de changer les choses?

Edit: Je devrais ajouter que tout le code de base à cet endroit a été compilé en même temps, de sorte qu'ils auraient pu penser que la modification de l'interface publique des classes (en modifiant un champ public en propriété) n'était pas un problème.

4
Moe Sisko

Les champs sont variables membres ordinaires ou des instances de membres d'une classe. Les propriétés sont un abstraction pour obtenir et définir leurs valeurs. Les propriétés sont également appelées accesseurs car elles offrent un moyen de modifier et de récupérer un champ si vous exposez un champ de la classe en tant que privé. En règle générale, vous devez déclarer vos variables de membre privées, puis déclarer ou définir des propriétés pour celles-ci.

  class SomeClass
  {
     int numbera; //Field

     //Property 
    public static int numbera { get; set;}

  }
4
Vasim Shaikh

En outre, les propriétés vous permettent d'utiliser la logique lors de la définition de valeurs.

Vous pouvez donc dire que vous voulez uniquement définir une valeur sur un champ entier, si la valeur est supérieure à x, sinon émettez une exception.

Fonctionnalité vraiment utile.

4
GurdeepS

Traditionnellement, les champs privés sont définis via les méthodes getter et setter. Par souci de moins de code, vous pouvez utiliser les propriétés pour définir des champs.

3
Chris Paine

De Wikipedia - Programmation orientée objet :

La programmation orientée objet (OOP) est un paradigme de programmation basé sur le concept des "objets", qui sont des structures de données contenant des données , sous la forme de champs , souvent appelés attributs; et du code, sous forme de procédures, souvent appelé méthodes . (italiques ajoutés)

Les propriétés font en fait partie du comportement d'un objet, mais sont conçues pour donner aux consommateurs de l'objet l'illusion/abstraction de travailler avec les données de l'objet.

3
Zev Spitz

Les propriétés encapsulent des champs, ce qui vous permet d'effectuer un traitement supplémentaire sur la valeur à définir ou à récupérer. Il est généralement excessif d'utiliser des propriétés si vous n'effectuez aucun pré-traitement ou post-traitement sur la valeur du champ.

3
Erik Burger

quand vous avez une classe qui est "voiture". Les propriétés sont couleur, forme ..

Les champs as sont des variables définies dans le cadre d'une classe.

3
user406580

Les champs sont les variables dans les classes. Les champs sont les données que vous pouvez encapsuler à l'aide de modificateurs d'accès.

Les propriétés sont similaires aux champs en ce qu'elles définissent des états et les données associées à un objet.

Contrairement à un champ, une propriété a une syntaxe spéciale qui contrôle la manière dont une personne lit et écrit les données. Celles-ci sont appelées opérateurs get et set. La logique d'ensemble peut souvent être utilisée pour effectuer une validation.

3
Neil Meyer

IMO, les propriétés ne sont que les paires fonctions/méthodes/interfaces "SetXXX ()" "GetXXX ()" que nous utilisions auparavant, mais elles sont plus concises et élégantes.

3
Junchao Xu

Ma conception d'un champ est qu'un champ doit être modifié uniquement par son parent, d'où la classe. Résultat la variable devient privée, alors pour pouvoir donner le droit de lire les classes/méthodes en dehors je vais dans le système de propriété avec seulement le Get. Le champ est ensuite récupéré par la propriété et en lecture seule! Si vous voulez le modifier, vous devez passer par des méthodes (par exemple le constructeur) et je trouve que grâce à cette façon de vous sécuriser, nous avons un meilleur contrôle sur notre code car nous "flangons". On pourrait très bien toujours tout mettre en public donc chaque cas possible, la notion de variables/méthodes/classes etc ... est à mon avis juste une aide au développement, à la maintenance du code. Par exemple, si une personne reprend un code avec des champs publics, elle peut tout faire et donc des choses "illogiques" par rapport à l'objectif, la logique de la raison pour laquelle le code a été écrit. C'est mon point de vue.

Lorsque j'utilise un modèle classique de propriétés de domaine privé/public en lecture seule, je devrais écrire 10 propriétés publiques pour 10 champs privés! Le code peut être très gros plus vite. Je découvre le poseur privé et maintenant je n'utilise plus que les propriétés publiques avec un poseur privé. Le poseur crée en arrière-plan un champ privé.

C'est pourquoi mon ancien style de programmation classique était:

public class MyClass
{
 private int _id;
 public int ID { get { return _id; } }
 public MyClass(int id)
 {
  _id = id;
 }
}

Mon nouveau style de programmation:

public class MyClass
{
 public int ID { get; private set; }
 public MyClass(int id)
 {
  ID = id;
 }
}
3
Tony Pinot

La différence fondamentale et générale est:

Des champs

  • TOUJOURS donne à la fois l'accès get et set
  • PEUT NE PAS POUVOIR provoquer des effets secondaires (exceptions générées, méthodes d'appel, champs modifiés sauf celui qui est obtenu/défini, etc.)

Propriétés

  • PAS TOUJOURS donner à la fois l'accès get et set
  • CAN provoquer des effets secondaires
2
Ted Mucuzany

Pensez-y: vous avez une pièce et une porte pour entrer dans cette pièce. Si vous voulez vérifier qui entre et sécuriser votre chambre, vous devez utiliser des propriétés, sinon elles ne seront pas une porte et toutes entreront facilement sans réglementation.

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

Les gens se rendent à la sectionUn assez facilement, il n'y a pas eu de vérification

class Room 
{
   private string sectionOne;
   private string sectionTwo;

   public string SectionOne 
   {
      get 
      {
        return sectionOne; 
      }
      set 
      { 
        sectionOne = Check(value); 
      }
   }
}

Room r = new Room();
r.SectionOne = "enter";

Maintenant, vous vérifiez la personne et savez s'il a quelque chose de mal avec elle

2
user8080469

La grande majorité des cas, il s'agira d'un nom de propriété auquel vous aurez accès, par opposition à un nom de variable ( champ ). La raison en est qu'il est considéré comme bon pratiquez en .NET et en C # en particulier pour protéger toutes les données d'une classe, qu'il s'agisse d'une variable d'instance ou d'une variable statique (variable de classe), car elles sont associées à une classe.

Protégez toutes ces variables avec les propriétés correspondantes qui vous permettent de définir , définir et obtenir accessors et faire des choses comme validation lorsque vous manipulez ces données.

Mais dans d'autres cas, comme classe Math (espace de noms système), quelques propriétés statiques sont intégrées à la classe. dont l'une est la constante mathématique PI

par exemple. Math.PI

et comme PI est un élément de données bien défini, nous n'avons pas besoin de plusieurs copies de PI, il s'agira toujours de la même valeur. Ainsi, les variables statiques sont parfois utilisées pour partager des données entre les objets d'une classe, mais elles sont également couramment utilisées pour des informations constantes dans lesquelles vous n'avez besoin que d'une copie d'une donnée.

2
Nermien Barakat

Les propriétés sont utilisées pour exposer le champ. Ils utilisent des accesseurs (set, get) à travers lesquels les valeurs des champs privés peuvent être lues, écrites ou manipulées.

Les propriétés ne nomment pas les emplacements de stockage. Au lieu de cela, ils ont des accesseurs qui lisent, écrivent ou calculent leurs valeurs.

En utilisant les propriétés, nous pouvons définir la validation sur le type de données défini sur un champ.

Par exemple, nous avons un champ de champ entier privé sur lequel nous devrions autoriser des valeurs positives car l’âge ne peut pas être négatif.

Nous pouvons le faire de deux manières en utilisant getter et setters et en utilisant property.

 Using Getter and Setter

    // field
    private int _age;

    // setter
    public void set(int age){
      if (age <=0)
       throw new Exception();

      this._age = age;
    }

    // getter
    public int get (){
      return this._age;
    }

 Now using property we can do the same thing. In the value is a key Word

    private int _age;

    public int Age{
    get{
        return this._age;
    }

    set{
       if (value <= 0)
         throw new Exception()
       }
    }

Propriété implémentée automatiquement Si nous ne faisons pas de logique dans les accesseurs get et set, nous pouvons utiliser la propriété implémentée automatiquement.

Lorsque u la propriété auto-implémentée compile crée un champ privé et anonyme accessible uniquement via des accesseurs get et set.

public int Age{get;set;}

Propriétés abstraites Une classe abstraite peut avoir une propriété abstraite, qui devrait être implémentée dans la classe dérivée

public abstract class Person
   {
      public abstract string Name
      {
         get;
         set;
      }
      public abstract int Age
      {
         get;
         set;
      }
   }

// overriden something like this
// Declare a Name property of type string:
  public override string Name
  {
     get
     {
        return name;
     }
     set
     {
        name = value;
     }
  }

Nous pouvons définir une propriété de manière privée. Pour cela, nous pouvons définir de manière privée la propriété auto (définie avec dans la classe).

public int MyProperty
{
    get; private set;
}

Vous pouvez réaliser la même chose avec ce code. Dans cet ensemble de propriétés, la fonctionnalité n'est pas disponible car nous devons définir la valeur sur le champ directement.

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}
2
Nayas Subramanian

Les propriétés sont un type spécial de membre de classe. Dans les propriétés, nous utilisons une méthode prédéfinie Set ou Get. Elles utilisent des accesseurs à travers lesquels nous pouvons lire, écrire ou modifier les valeurs des champs privés.

Par exemple, prenons une classe nommée Employee, avec des champs privés pour nom, âge et Employee_Id. Nous ne pouvons pas accéder à ces champs de l'extérieur de la classe, mais nous pouvons accéder à ces champs privés via des propriétés.

Pourquoi utilisons-nous des propriétés?

Rendre le champ de classe public et l'exposer est risqué, car vous ne contrôlerez pas ce qui sera assigné et retourné.

Pour comprendre cela clairement avec un exemple, prenons un cours avec un ID, PassMark, name. Maintenant, dans cet exemple, un problème avec le champ public

  • ID ne devrait pas être -ve.
  • Le nom ne peut pas être défini sur null
  • La note de passage devrait être en lecture seule.
  • Si le nom de l'étudiant est manquant, aucun nom ne devrait être renvoyé.

Pour supprimer ce problème, nous utilisons la méthode Get and set.

// A simple example
public class student
{
    public int ID;
    public int PassMark;
    public string name;
}

public class Program
{
    public static void Main(string[] args)
    {
       student s1 = new student();
       s1.ID = -101; // here ID can't be -ve
       s1.Name = null ; // here Name can't be null
    }
}

Maintenant, prenons un exemple de la méthode get and set

public class student
{
    private int _ID;
    private int _PassMark;
    private string_name ;
    // for id property
    public void SetID(int ID)
    {
        if(ID<=0)
        {
            throw new exception("student ID should be greater then 0");
        }
        this._ID = ID;
    }
    public int getID()
    {
        return_ID;
    }
}
public class programme
{
    public static void main()
    {
        student s1 = new student ();
        s1.SetID(101);
    }
    // Like this we also can use for Name property
    public void SetName(string Name)
    {
        if(string.IsNullOrEmpty(Name))
        {
            throw new exeception("name can not be null");
        }
        this._Name = Name;
    }
    public string GetName()
    {
        if( string.IsNullOrEmpty(This.Name))
        {
            return "No Name";
        }
        else
        {
            return this._name;
        }
    }
        // Like this we also can use for PassMark property
    public int Getpassmark()
    {
        return this._PassMark;
    }
}
2
ahmed alkhatib

Bien que les champs et les propriétés semblent être similaires, ils constituent deux éléments de langage complètement différents.

  1. Les champs sont le seul mécanisme permettant de stocker des données au niveau de la classe. Les champs sont des variables conceptuelles au niveau de la classe. Si vous souhaitez stocker des données dans des instances de vos classes (objets), vous devez utiliser des champs. Il n'y a pas d'autre choix. Les propriétés ne peuvent stocker aucune donnée, même si elles ont l’impression de pouvoir le faire. Voir ci-dessous.

  2. En revanche, les propriétés ne stockent jamais de données. Ce ne sont que des paires de méthodes (get et set) qui peuvent être appelées de manière syntaxique de la même manière que des champs et dans la plupart des cas, elles accèdent (en lecture ou en écriture). ), source de confusion. Mais comme les méthodes de propriété sont (avec certaines limitations comme le prototype fixe) des méthodes C # régulières, elles peuvent faire tout ce que peuvent faire les méthodes habituelles. Cela signifie qu'ils peuvent avoir 1 000 lignes de code, qu'ils peuvent générer des exceptions, appeler d'autres méthodes, qu'ils peuvent même être virtuels, abstraits ou remplacés. La particularité des propriétés est que le compilateur C # stocke des métadonnées supplémentaires dans des assemblys qui peuvent être utilisés pour rechercher des propriétés spécifiques - une fonctionnalité largement utilisée.

Les méthodes de propriété Get et set ont les prototypes suivants.

PROPERTY_TYPE get();

void set(PROPERTY_TYPE value);

Cela signifie donc que les propriétés peuvent être "émulées" en définissant un champ et 2 méthodes correspondantes.

class PropertyEmulation
{
    private string MSomeValue;

    public string GetSomeValue()
    {
        return(MSomeValue);
    }

    public void SetSomeValue(string value)
    {
        MSomeValue=value;
    }
}

Une telle émulation de propriété est typique des langages de programmation qui ne prennent pas en charge les propriétés, comme le C++ standard. En C #, vous devriez toujours préférer les propriétés comme moyen d’accéder à vos champs.

Étant donné que seuls les champs peuvent stocker des données, cela signifie que plus de champs de classe sont contenus, plus d’objets mémoire de cette classe seront consommés. D'autre part, l'ajout de nouvelles propriétés dans une classe ne rend pas les objets d'une telle classe plus grands. Voici l'exemple.

class OneHundredFields
{
        public int Field1;
        public int Field2;
        ...
        public int Field100;
}

OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.

class OneHundredProperties
{
    public int Property1
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    public int Property2
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    ...

    public int Property100
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }
}

OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).

Bien que les méthodes de propriété puissent faire n'importe quoi, elles servent dans la plupart des cas à accéder aux champs des objets. Si vous voulez rendre un champ accessible à d'autres classes, vous pouvez le faire de deux manières.

  1. Rendre les champs publics - déconseillé.
  2. Utilisation de propriétés.

Voici une classe utilisant des champs publics.

class Name
{
    public string FullName;
    public int YearOfBirth;
    public int Age;
}

Name name=new Name();

name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;

Bien que le code soit parfaitement valide, il présente plusieurs inconvénients du point de vue de la conception. Les champs pouvant être lus et écrits, vous ne pouvez pas empêcher l'utilisateur d'écrire dans les champs. Vous pouvez appliquer le mot clé readonly, mais vous ne devez ainsi initialiser les champs en lecture seule que dans le constructeur. De plus, rien ne vous empêche de stocker des valeurs non valides dans vos champs.

name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;

Le code est valide, toutes les assignations seront exécutées bien qu’elles soient illogiques. Age a une valeur négative, YearOfBirth est loin dans le futur et ne correspond pas à Age et FullName est nul. Avec les champs, vous ne pouvez pas empêcher les utilisateurs de class Name de faire de telles erreurs.

Voici un code avec des propriétés qui résout ces problèmes.

class Name
{
    private string MFullName="";
    private int MYearOfBirth;

    public string FullName
    {
        get
        {
            return(MFullName);
        }
        set
        {
            if (value==null)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MFullName=value;
        }
    }

    public int YearOfBirth
    {
        get
        {
            return(MYearOfBirth);
        }
        set
        {
            if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MYearOfBirth=value;
        }
    }

    public int Age
    {
        get
        {
            return(DateTime.Now.Year-MYearOfBirth);
        }
    }

    public string FullNameInUppercase
    {
        get
        {
            return(MFullName.ToUpper());
        }
    }
}

La version mise à jour de class présente les avantages suivants.

  1. FullName et YearOfBirth sont vérifiés pour les valeurs non valides.
  2. Age n'est pas enregistrable. Il est appelé à partir de YearOfBirth et de l'année en cours.
  3. Une nouvelle propriété FullNameInUppercase convertit FullName en MAJUSCULES. Ceci est un petit exemple artificiel d'utilisation de propriété, où les propriétés sont couramment utilisées pour présenter les valeurs de champ dans le format qui convient le mieux à l'utilisateur - par exemple, en utilisant les paramètres régionaux actuels sur un format numérique spécifique DateTime.

A côté de cela, les propriétés peuvent être définies comme virtuelles ou remplacées - simplement parce que ce sont des méthodes .NET standard. Les mêmes règles s'appliquent aux méthodes de propriétés telles que pour les méthodes ordinaires.

C # prend également en charge les indexeurs qui sont les propriétés qui ont un paramètre d'index dans les méthodes de propriété. Voici l'exemple.

class MyList
{
    private string[]                 MBuffer;

    public MyList()
    {
        MBuffer=new string[100];
    }

    public string this[int Index]
    {
        get
        {
            return(MBuffer[Index]);
        }
        set
        {
            MBuffer[Index]=value;
        }
    }
}

MyList   List=new MyList();

List[10]="ABC";
Console.WriteLine(List[10]);

Puisque C # 3.0 vous permet de définir des propriétés automatiques. Voici l'exemple.

class AutoProps
{
    public int Value1
    {
        get;
        set;
    }

    public int Value2
    {
        get;
        set;
    }
}

Même si class AutoProps ne contient que des propriétés (ou l’apparence), il peut stocker 2 valeurs et la taille des objets de cette classe est égale à sizeof(Value1)+sizeof(Value2) = 4 + 4 = 8 octets.

La raison en est simple. Lorsque vous définissez une propriété automatique, le compilateur C # génère un code automatique contenant un champ masqué et une propriété avec des méthodes de propriété accédant à ce champ masqué. Voici le compilateur de code produit.

Voici un code généré par le ILSpy à partir de l'Assemblée compilée. La classe contient les champs et propriétés masqués générés.

internal class AutoProps
{
    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value1>k__BackingField;

    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value2>k__BackingField;

    public int Value1
    {
        [CompilerGenerated]
        get
        {
            return <Value1>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value1>k__BackingField = value;
        }
    }

    public int Value2
    {
        [CompilerGenerated]
        get
        {
            return <Value2>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value2>k__BackingField = value;
        }
    }
}

Ainsi, comme vous pouvez le constater, le compilateur utilise toujours les champs pour stocker les valeurs - car les champs sont le seul moyen de stocker des valeurs dans des objets.

Ainsi, comme vous pouvez le constater, bien que les propriétés et les champs aient une syntaxe d'utilisation similaire, il s'agit de concepts très différents. Même si vous utilisez des propriétés ou des événements automatiques, les champs masqués sont masqués. généré par le compilateur où les données réelles sont stockées.

Si vous devez rendre une valeur de champ accessible au monde extérieur (utilisateurs de votre classe), n'utilisez pas de champs publics ou protégés. Les champs doivent toujours être marqués comme privés. Les propriétés vous permettent de vérifier les valeurs, le formatage, les conversions, etc. et rendent généralement votre code plus sûr, plus lisible et plus extensible pour les modifications futures.

1
Timmy_A

Informations supplémentaires: Par défaut, les accesseurs get et set sont aussi accessibles que la propriété elle-même. Vous pouvez contrôler/restreindre l'accessibilité des accesseurs individuellement (pour get et set) en leur appliquant des modificateurs d'accès plus restrictifs.

Exemple:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

Ici, get est toujours accessible au public (la propriété est publique), mais set est protégé (spécificateur d'accès plus restreint).

1
Django