web-dev-qa-db-de.com

C # public -Variable als innerhalb der Klasse schreibbar, jedoch außerhalb der Klasse schreibgeschützt

Ich habe eine .Net C # -Klasse, in der ich eine Variable veröffentlichen muss. Ich muss diese Variable innerhalb einer Methode (nicht innerhalb des Konstruktors) initialisieren. Ich möchte jedoch nicht, dass die Variable von anderen Klassen geändert werden kann. Ist das möglich?

36
MikeTWebb

Verwenden Sie kein Feld - verwenden Sie eine Eigenschaft:

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

In diesem Beispiel kann Foo.Bar überall gelesen und nur von Mitgliedern von Foo selbst beschrieben werden.

Als Nebenbemerkung verwendet dieses Beispiel eine in Version 3 eingeführte C # -Funktion namens Automatisch implementierte Eigenschaften . Hierbei handelt es sich um einen syntaktischen Zucker, den der Compiler in eine reguläre Eigenschaft mit einem privaten Hintergrundfeld wie dem folgenden umwandeln wird:

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

Sie müssen dazu eine Eigenschaft verwenden. Wenn Sie mit einer automatischen Getter/Setter-Implementierung zufrieden sind, wird dies funktionieren:

public string SomeProperty { get; private set; }

Beachten Sie, dass Sie Felder sowieso nicht als öffentlich verfügbar machen sollten, außer unter bestimmten Umständen. Verwenden Sie stattdessen eine Eigenschaft.

6
cdhowie

Sicher. Machen Sie es zu einer Eigenschaft und machen Sie den Setter privat:

public Int32 SomeVariable { get; private set; }

Dann setzen Sie es (aus einer Methode in der Klasse):

SomeVariable = 5;
4
Chris Shain

Verwenden Sie eine private Variable und machen Sie eine öffentliche Eigenschaft verfügbar.

class Person
{
  private string name;

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

Dürfen Sie keine Immobilie dafür verwenden? Wenn du bist:

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

Necro sicher, aber dies erwähnt die Verbesserungen der Sprache in 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

Die bisherigen Antworten funktionieren gut, solange Sie keine Referenztypen verwenden. Andernfalls können Sie immer noch das Innere dieser Variablen manipulieren. Z. B.

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; }
        }
    }
}
Dies führt zur Ausgabe der Konsole:

Hello World!
Changed it!

Welches ist möglicherweise genau das, was Sie möchten, da Sie nicht in der Lage sein werden, dies zu ändern SomeBar . Wenn Sie jedoch das Innere der Variablen nicht ändern möchten, müssen Sie eine Kopie der Variablen zurückgeben, z. B.


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;
            }
        }
    }
}
, der zur Ausgabe führt:

Hello World!
Hello World!

Siehe Kommentare, warum ich das dritte Beispiel hinzugefügt habe:


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