web-dev-qa-db-fra.com

Une propriété implémentée en lecture seule est-elle possible?

J'ai trouvé un sujet sur MSDN qui dit que oui, c'est possible.

J'ai fait un test qui semble casser cette affirmation:

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo f = new Foo("1");
            Console.WriteLine(f.Bar); // prints 1
            f.Test("2");
            Console.WriteLine(f.Bar);// successfully prints 2
        }
    }

    class Foo
    {
        public Foo(string b)
        {
            this.Bar = b;
        }

        public string Bar { get; private set; }

        public void Test(string b)
        {
            // this would be impossible for readonly field!
            // next error would be occur: CS0191 or CS0191
            // A readonly field cannot be assigned to (except in a constructor or a variable initializer)
            this.Bar = b; 
        }
    }
}

Où ai-je tort?

59
abatishchev

La réponse ci-dessous a été écrite en 2010. En C # 6 (sorti en 2015), vous pouvez écrire des propriétés implémentées automatiquement en lecture seule:

// This can only be assigned to in a constructor
public int Foo { get; }

Vous avez absolument raison. Les propriétés implémentées correctement en lecture seule sont actuellement impossibles. Rendre le setter privé n'est pas la même chose, indépendamment de ce que certains livres et MSDN pourraient dire :)

Si je dirigeais le monde, ce ne serait pas le cas. Quand je vois certains des concepteurs de langage à NDC 201 en juin (venez s'il vous plaît!) J'ai l'intention d'essayer de persuader, de soudoyer, de cajoler et généralement de me déranger jusqu'à ce qu'ils soient d'accord. Ce n'est qu'une fonction ultra-mince , après tout.

En regardant cet article MSDN, le texte lui-même ne dit pas qu'il crée une propriété automatique en lecture seule. Il crée un type immuable en utilisant une propriété automatique, et c'est correct. Les seuls morceaux problématiques sont les commentaires disant

// Read-only properties.

... qui sont définitivement faux. Le cadre est d'accord avec nous:

var prop = typeof(Contact).GetProperty("Name");
Console.WriteLine(prop.CanWrite); // Prints True
100
Jon Skeet

La propriété est en lecture seule en dehors de la classe Foo. Je pense que c'est l'objet de l'article.

Mais ce n'est pas la même chose que de marquer une variable avec le mot clé readonly.

8
kervin

C'est confu. Vous devez différencier en lecture seule le c # readonly (ce que signifie le mot-clé).

  • lecture seule: ils signifient que personne à l'extérieur ne peut y écrire directement, seulement lire.
  • C # readonly: vous ne pouvez y écrire que dans le constructeur, puis jamais plus.
6
Samuel Carrijo

Non, il n'est pas possible de créer une propriété implémentée automatiquement en lecture seule. Pour la page que vous avez liée:

avec des propriétés implémentées automatiquement, un accesseur get et set sont requis

Une propriété en lecture seule n'a AUCUN accesseur défini.

ne propriété sans accesseur défini est considérée en lecture seule

4
Ben Voigt

Le mot clé ReadOnly, en C # et VB, fait la même chose lorsqu'il est appliqué à un champ. Ils font en sorte que le champ ne soit assignable que pendant l'initialisation statique (s'il est marqué comme champ statique/partagé) ou pendant le constructeur.

C # n'utilise le mot clé en lecture seule pour rien d'autre.

Le mot clé ReadOnly dans VB prend une signification différente lorsqu'il est appliqué à une propriété. Dans ce cas, cela signifie simplement qu'il n'existe aucun moyen acceptable d'assigner à la propriété publique (en interne, le champ de support peut être modifié autre code interne, bien sûr).

1
user1739635

L'ensemble privé n'est pas le même que readonly.

Semblable aux méthodes ou aux champs, le mot clé private rend la visibilité du setter disponible uniquement pour la classe elle-même. D'autres objets ne peuvent pas utiliser le setter, mais les méthodes de la classe elle-même peuvent l'appeler librement. Par conséquent, votre code de test se compile et fonctionne correctement.

Elle apparaît aux objets externes comme une propriété readonly, mais elle n'est pas en lecture seule dans la vraie définition.

1
womp

Il n'est pas possible de créer une propriété readonly auto-implémentée. Si vous essayez de compiler une classe avec une propriété implémentée automatiquement, vous obtiendrez cette erreur si elle n'a pas à la fois get et set:

'ProjectName.ClassName.Property.get' doit déclarer un corps car il n'est pas marqué comme abstrait ou externe. Les propriétés implémentées automatiquement doivent définir les accesseurs get et set.

La phrase commençant par "Automatiquement" est la partie de l'erreur qui nous préoccupe.

1
Jose Alava