Подтвердить что ты не робот

Открытая переменная С# как записываемая внутри класса, но только для чтения вне класса

У меня есть класс .Net С#, где мне нужно сделать переменную общедоступной. Мне нужно инициализировать эту переменную внутри метода (не внутри конструктора). Однако я не хочу, чтобы переменная изменялась другими классами. Возможно ли это?

4b9b3361

Ответ 1

Не используйте поле - используйте свойство:

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

В этом примере Foo.Bar читается везде и записывается только членами самого Foo.

В качестве дополнительного примечания в этом примере используется функция С#, введенная в версии 3, которая называется автоматически реализованными свойствами. Это синтаксический сахар, который компилятор преобразует в регулярное свойство, которое имеет частное поле поддержки следующим образом:

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;
        }
    }
}

Ответ 2

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

Ответ 3

Для этого вам нужно использовать свойство. Если у вас все в порядке с автоматическим внедрением getter/setter, это будет работать:

public string SomeProperty { get; private set; }

Обратите внимание, что вы не должны публиковать поля как общедоступные, за исключением некоторых ограниченных обстоятельств. Вместо этого используйте свойство.

Ответ 4

Конечно. Сделайте это свойством и сделайте setter частным:

public Int32 SomeVariable { get; private set; }

Затем, чтобы установить его (изнутри некоторого метода в классе):

SomeVariable = 5;

Ответ 5

Использовать закрытую переменную и открыть публичное свойство.

class Person
{
  private string name;

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

Ответ 6

Вам не разрешено использовать свойство для этого? Если вы:

private string _variable
public string Variable {
    get {
        return _variable;
    }
}

Ответ 7

Necro наверняка, но это говорит об улучшениях языка в 6.0

class Foo {

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

    }

Ответ 8

Ответы до сих пор работают хорошо, пока вы не используете ссылочные типы. В противном случае вы все равно сможете манипулировать внутренними элементами этой переменной. например:

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; }
        }
    }
}
This will result in the console output:
Hello World!
Changed it!

Какой может быть именно то, что вы хотите, поскольку вы не сможете изменить SomeBar, но если вы хотите, чтобы внутренности переменной не изменялись, вам нужно передать копию переменной, например:


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;
            }
        }
    }
}
which will result in the output:
Hello World!
Hello World!

См. комментарии, почему я добавил третий пример:


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;
            }
        }
    }
}

Ответ 9

Определите это как личное? Это то, о чем вы просите, вы можете изменить его в любом месте внутри класса контейнера, но вы не можете его обойти.