Property, avantages réels ?

[Résolu]
Signaler
Messages postés
1024
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
7 juin 2010
-
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
-
Hello,

On m'a posé une question récemment à laquelle j'ai été bien embêter pour répondre.

On présente souvent des exemples avec des propriétés simples :

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

La question était : dans un cas aussi simple, quel est l'avantage réel de mettre Text comme property plutôt que de mettre public la variable ?
Dans un cas plus compliqué, ou si on ne veut pas de set, je peux comprendre, mais dans un cas simpliste comme celui-ci, le seul effet que je vois, est de ralentir un peu le programme.
Si vous pouviez me donner une bonne raison d'utiliser les properties dans des cas semblabes, j'aurai apris quelque chose aujourd'hui.

Merci à tous, SharpMao

18 réponses

Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
c'est surtout un principe de la programmation objet.

on ne doit jamais exposer publiquement les membres d'une classe. Il faut pour cela exposer des accesseurs.

Sébastien FERRAND (
blog)
Consultant Indépendant
[Microsoft MVP Visual C#]
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Modérateur
Dernière intervention
30 octobre 2008
54
Pourtant, c'est vrai que dans un cas aussi simple que celui de ton exemple, c'est pas si facile de trouver une utilité.
Mais j'adhère aux reponses des mes collegues, principe de prog objet.

Mais j'ai eu moins une utilité reelle en tete : DataBinding. On utilise les propriétés pour le binding, pas les champs.

Mx
MVP C# 
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
56
Petit article sur MSDN sur le sujet.
Il m'avait pourtant sembler lire un jour qu'une variable public pouvait poser des problèmes de sécurité.
Ma mémoire me jouerait t'elle (déjà) des tours? 

<hr size="2" />-Blog-
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
39
Property = appel de méthode, c'est donc forcement plus long à moins que le compilateur optimise et "inline" la méthode.

Dans certains cas je me passe des propriétés, surtout pour les structures.
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
56
Salut,
Je ne connais pas les détails (malheureusement) mais il s'agit d'une question de sécurité... il ne faut en prinicipe pas exposer les variables au monde extérieur (c'est à dire, les rendre publique).
De plus, je ne pense pas qu'une Property soit plus lente...

Peut-être que quelqu'un d'autre pourra te donner un peu plus d'infos....

<hr size="2" />-Blog-
Messages postés
1024
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
7 juin 2010
64
Hello,

Merci pour vos réponses. Je retiens donc



<li>le principe de POO (oui, mais un principe se devrait d'avoir une raison solide)</li>
<li>Le DataBindimg</li>
<li>La sécurité ? Si quelqu'un retrouve un article à ce sujet, je suis preneur.</li>

Quant à la question de la vitesse, oui, c'est plus rapide d'accéder à une variable qu'à une propriété. J'ai fait le test suivant :



Class1

c1 =

new



Class1


();


Class2
c2 =

new



Class2


();


DateTime
dt1 =

DateTime


.Now;


for
(

int
i = 0; i <

int


.MaxValue; i++)
   c1.Count = i;


TimeSpan
ts1 =

DateTime


.Now - dt1;


DateTime
dt2 =

DateTime


.Now;


for
(

int
i = 0; i <

int


.MaxValue; i++)
   c2.Count = i;


TimeSpan
ts2 =

DateTime

.Now - dt2;



Class1 exposant sa variable Count, et Class2 ayant une propriété Count.

Résultat : 




<li>
ts1.TotalMilliseconds = 3642

</li>
<li>
ts2.TotalMilliseconds = 12302

</li>

Soit tout de même un coefficient de 3.38

Amicalement, SharpMao
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
56
Je n'arrive pas du tout au même résultat (j'ai utilisé la classStopWatch pour les calculs)
Voici mes résultats :

Lecture
3830477304
3601111444
Ecriture
27614531672
27878963156

Les nombres représentent les ticks écoulés. Le premier chiffre avec la variable, le deuxième avec la property, une fois en lecture et une fois en écriture.

Constat (j'ai fait le teste quelque fois, et j'obtients des résultats similaires)

- La lecture semble plus rapide avec une Property
- L'écriture semble un peu plus lente avec la Property, mais le coefficient est très faible.

<hr size="2" />-Blog-
Messages postés
1024
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
7 juin 2010
64
Hello,


J'ai refait mon test en utilisant les Stopwatch.


J'ai même fait une boucle vide pour regarder le temps de la boucle elle-même. Et mes résultats sont toujours les mêmes, pire encore si on enlève le temps de la boucle :


Boucle vide : 13 * 10^9
Boucle variable : 17.4 *10^9
Boucle property : 42.5 *10^9

Donc, une fois enlevé le temps de la boucle, un rapport de 6.7!
Je ne sais pas où nos test diffèrent, mais différence il y a !

Amicalement, SharpMao
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
56
Hum, comment t'as codé les deux classes?

    public class Class1
    {
        public string test = "salut";
    }


    public class Class2
    {
        private string _test = "salut";
        public string Test { get { return this._test; } set { this._test = value; } }
    }

Un rapport de quasiement 7x me paraît assez peu probable je dois dire...
Mais j'explique toutefois pas le fait que nos tests soient autant différents...










<hr size="2" />



-Blog-
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
56
Hum, j'espère que tu as fait ton teste en démarrant l'exécutable et en ayant fait une compilation en mode release ?!

<hr size="2" />-Blog-
Messages postés
1024
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
7 juin 2010
64
Pour Bidou,

mon code est semblable au tien, à la différence que j'ai utilisé des int à la place des string.

Pour Lutinore,
Je pensais aussi que la différence de temps venait de ça. J'ai d'ailleurs donné un petit coup d'ildasm à mon code :

Variable :
.field public int32 Count

Property :




.method public hidebysig specialname instance int32






get_Count() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 TestDivers.Class2::_count
IL_0006: ret
} // end of method Class2::get_Count


.method public hidebysig specialname instance void
set_Count(int32 'value') cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 TestDivers.Class2::_count
IL_0007: ret
} // end of method Class2::set_Count


Donc clairement plus à faire dans le cas d'une propriété.

Enfin. J'ai tout de même eu un début de réponse à ma question grace à vous.
Merci

Amicalement, SharpMao
Messages postés
256
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
6 novembre 2009
1
Vous avez tout faux messieurs :
- d'abord, vu la rapidité des processeurs d'aujourd'hui on ne cherche plus à gagner la milliseconde
- Deuzio, les propriétés permettent de créer un niveau d'abstraction qui autorise de changer l'implémentation interne d'un objet sans obliger les utilisateurs de l'objet à s'adapter : ca s'appelle l'encapsulation.
- Par exemple, si votre objet travail avec une liste de strings , vous pouvez tres bien travailler en interne avec une List(of string) un arraylist ou tout autre chôse et n'exposer à l'utilisateur que les fonctions d'accès à cette liste (Item(...) , Add(), Count, delete....).
- Terzio, utiliser une property plutot qu'une variable publique permet de vérifier les contraintes sur les valeurs directement à l'endroit où la valeur est lu ou écrite.
- Quatrezio, Quand vous voulez faire du readonly déclarer votre variable en readonly, cela ne doit pas être une raison de créér une property avec seulement GET. On crée une property quand on veux masquer l'implémentation interne d'un objet.

Voila c'est à peu près tout.

Jcbé[^]
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
39
"Vous avez tout faux messieurs :"


Heureusement que tu es là alors..



"- d'abord, vu la rapidité des processeurs d'aujourd'hui on ne cherche plus à gagner la milliseconde"

Si si, même ( surtout ) en code managé, un peu d'optimisation ça ne fait pas de mal.. Et puis on parlait du principe, on ne t'a pas demandé si on voulait ou pas gagner quelques millisecondes.



"- Deuzio, les propriétés permettent de créer un niveau d'abstraction qui autorise de changer l'implémentation interne d'un objet sans obliger les utilisateurs de l'objet à s'adapter : ca s'appelle l'encapsulation."


Oui oui le principe de la POO, ça été cité par Sebmafate et MorpionMx.



"- Terzio, utiliser une property plutot qu'une variable publique permet de vérifier les contraintes sur les valeurs directement à l'endroit où la valeur est lu ou écrite."


Oui mais là, la question portait clairement sur un cas de figure ou justement il n y a aucun test de contraintes ou de valeurs.



"- Quatrezio, Quand vous voulez faire du readonly déclarer votre variable en readonly, cela ne doit pas être une raison de créér une property avec seulement GET. On crée une property quand on veux masquer l'implémentation interne d'un objet."


Pourquoi on a dit le contraire !?



"Voila c'est à peu près tout."


Voila c'est ça..
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Modérateur
Dernière intervention
30 octobre 2008
54
Merci Lutinore

En plus, on parlait simplement dans le cas de l'exemple simple proposé pa SharpMao, pas de l'avantage des propriétés tout court...

Mx
MVP C# 
Messages postés
256
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
6 novembre 2009
1
Ok. Je suis passé pour un c...
Mes plattes excuses Messieurs, je me retire donc sur la pointe des pieds.

Jcbé[^]
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Modérateur
Dernière intervention
30 octobre 2008
54
J'irais pas jusque là ;)
Y'a juste certaines façons pour dire les choses.

Le fond du message est juste. Il manquait juste la forme  (Du moins pour ma part, je l'ai ressenti comme ca)

Mx
MVP C# 
Messages postés
256
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
6 novembre 2009
1
- Merci. Mais je persiste à préférer un programme bien fait et lisible même si il est plus lent. Mais bon, si tu fais du temps réél, la y a pas de doute il faut aller chasser la microseconde.
- Mais qui voudrait faire du temps réél en dotnet ?.
Je dois cependant avouer que je n'utilise pas ilsdam, et que mes utilisations de la plateforme sont purement "bureautique" et réseau. Je ne suis donc pas le mieux placé pour juger.

Quoi qu'il en soit,j'apprécie et respecte le franc parler et la passion qui vous anime !

Bonne continuation.




Jcbé[^]
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
93
Salut,

J'arrive largement après la bataille, mais tant pis, je vais quand même donner mon avis ^^

C'est vrai que dans ce cas simple on ne voit pas forcément l'intérêt, et on pourrait s'arrêter aux pertes de temps causés par l'appel de méthode.

Mais au final pour moi la lisibilité, la continuité avec le restant du code (pour lequel les propriétés se "justifient") et surtout l'aspect évolution prédominent.
Et si dans la v2 on veut réagir à un changement de valeur du texte, effectuer un traitement quelconque dessus etc, on est bien embêtés avec notre champs :p (sans briser le code existant)
Il s'agit d'un membre exposé publiquement, comment faire la validation de la valeur qui s'impose sur un champs ? (je pense que ça rejoint en partie l'argument du problème de sécurité cité précédemment). Et si on se dit "pas besoin de validation là" et que par la suite on s'aperçoit qu'il s'agissait d'une énorme erreur, comment ajouter la validation sans briser le code existant si c'est un champs ?

Sinon, en vrac :
- on ne peut définir de champs dans une interface
- on ne peut surcharger un champs
- avec une propriété, on peut ajouter du code de debug, trace...
- j'aime les propriétés ! (ok, celui là ne compte pas :p)

Voilà, s'il y avait besoin d'un autre avis, c'est fait :p

Après pour tout ce qui est optimisation et différences en profondeur, j'avoue ne pas m'être pencher suffisamment sur le fond du sujet.

/*
coq
MVP Visual C#
CoqBlog
*/