web-dev-qa-db-fra.com

Variable publique C # accessible en écriture dans la classe mais en lecture seule hors de la classe

J'ai une classe .Net C # où j'ai besoin de rendre une variable publique. J'ai besoin d'initialiser cette variable dans une méthode (pas dans le constructeur). Cependant, je ne veux pas que la variable soit modifiable par d'autres classes. Est-ce possible?

36
MikeTWebb

Ne pas utiliser un champ - utiliser une propriété:

class Foo
{
    public string Bar { get; private set; }
}

Dans cet exemple, Foo.Bar est lisible partout et ne peut être écrit que par les membres de Foo lui-même.

Remarque: cet exemple utilise une fonctionnalité C # introduite dans la version 3, appelée propriétés automatiquement implémentées . C'est le sucre syntaxique que le compilateur transformera en une propriété standard qui possède un champ de sauvegarde privé comme celui-ci:

class Foo
{
    [CompilerGenerated]
    private string <Bar>k__BackingField;

    public string Bar
    {
        [CompilerGenerated]
        get
        {
            return this.<Bar>k__BackingField;
        }
        [CompilerGenerated]
        private set
        {
            this.<Bar>k__BackingField = value;
        }
    }
}
65
Andrew Hare
public class Foo
{
  public string Bar { get; private set; } 
}
11
3Dave

Vous devez utiliser une propriété pour cela. Si vous êtes d'accord avec une implémentation automatique du getter/setter, cela fonctionnera:

public string SomeProperty { get; private set; }

Notez que vous ne devez de toute façon pas exposer les champs comme publics, sauf dans certaines circonstances limitées. Utilisez plutôt une propriété.

6
cdhowie

Sûr. Faites-en une propriété et rendez le setter privé:

public Int32 SomeVariable { get; private set; }

Ensuite, pour le définir (depuis une méthode de la classe):

SomeVariable = 5;
4
Chris Shain

Utilisez une variable privée et exposez une propriété publique.

class Person
{
  private string name;

  public string Name
  {
    get
    {
      return name;
    }
  }
}
3
Henrik

Vous n'êtes pas autorisé à utiliser une propriété pour cela? Si vous êtes:

private string _variable
public string Variable {
    get {
        return _variable;
    }
}
2
Anders Arpi

Necro bien sûr, mais cela mérite d'être mentionné avec les améliorations apportées au langage dans la version 6.0

class Foo {

    // The new assignment constructor is wonderful shorthand ensuring
    // that the var is only writable inside the obj's constructor
    public string Bar { get; } = String.Empty;

    }
1
MisterNad

Jusqu'ici, les réponses fonctionnent bien tant que vous n'utilisez pas de types de référence. Sinon, vous pourrez toujours manipuler les éléments internes de cette variable. Par exemple:

using System;
namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var fo = new Fo();
            fo.Init();
            Console.WriteLine(fo.SomeBar.SomeValue);
            fo.SomeBar.SomeValue = "Changed it!";
            Console.WriteLine(fo.SomeBar.SomeValue);
            Console.Read();
        }
        public class Fo
        {
            public Bar SomeBar { get; private set; }
            public void Init()
            {
                SomeBar = new Bar{SomeValue = "Hello World!"};
            }
        }
        public class Bar
        {
            public String SomeValue { get; set; }
        }
    }
}
Ceci produira la sortie de la console:

Hello World!
Changed it!

Ce qui peut être exactement ce que vous voulez car vous ne pourrez pas changer SomeBar mais si vous voulez rendre les éléments internes de la variable non modifiables, vous devez renvoyer une copie de la variable, par exemple :


using System;
namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var fo = new Fo();
            fo.Init();
            Console.WriteLine(fo.SomeBar.SomeValue);
            fo.SomeBar.SomeValue = "Changed it!";
            Console.WriteLine(fo.SomeBar.SomeValue);
            Console.Read();
        }
        public class Fo
        {
            private Bar _someHiddenBar;
            public Bar SomeBar => new Bar(_someHiddenBar);
            public void Init()
            {
                _someHiddenBar = new Bar{SomeValue = "Hello World!"};
            }
        }
        public class Bar
        {
            public String SomeValue { get; set; }
            public Bar(){}
            public Bar(Bar previousBar)
            {
                SomeValue = previousBar.SomeValue;
            }
        }
    }
}
qui aura pour résultat la sortie:

Hello World!
Hello World!

Voir les commentaires pour savoir pourquoi j'ai ajouté le troisième exemple:


using System;
namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var fo = new Fo();
            fo.Init();
            Console.WriteLine(fo.SomeBar.SomeValue);
            //compile error
            fo.SomeBar.SomeValue = "Changed it!";
            Console.WriteLine(fo.SomeBar.SomeValue);
            Console.Read();
        }
        public class Fo
        {
            private Bar _someHiddenBar;
            public Bar SomeBar => new Bar(_someHiddenBar);
            public void Init()
            {
                _someHiddenBar = new Bar("Hello World!");
            }
        }
        public class Bar
        {
            public String SomeValue { get; }
            public Bar(string someValue)
            {
                SomeValue = someValue;
            }
            public Bar(Bar previousBar)
            {
                SomeValue = previousBar.SomeValue;
            }
        }
    }
}

0
kkCosmo