web-dev-qa-db-ja.com

クラス内では書き込み可能であるがクラス外では読み取り専用としてのC#パブリック変数

変数をパブリックにする必要がある.Net C#クラスがあります。この変数を(コンストラクター内ではなく)メソッド内で初期化する必要があります。ただし、他のクラスが変数を変更できるようにしたくありません。これは可能ですか?

42
MikeTWebb

フィールドを使用しないでください-プロパティを使用してください:

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

この例ではFoo.Barはどこでも読み取り可能で、Foo自体のメンバーのみが書き込み可能です。

ちなみに、この例では、バージョン3で導入された自動実装プロパティと呼ばれるC#機能を使用しています。これは、コンパイラーが次のようなプライベートバッキングフィールドを持つ通常のプロパティに変換する構文上の砂糖です。

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;
        }
    }
}
79
Andrew Hare
public class Foo
{
  public string Bar { get; private set; } 
}
12
3Dave

これにはプロパティを使用する必要があります。自動ゲッター/セッター実装で問題がなければ、これはうまくいきます:

public string SomeProperty { get; private set; }

限られた状況を除いて、フィールドをパブリックとして公開しないでください。代わりにプロパティを使用してください。

6
cdhowie

承知しました。プロパティにし、セッターをプライベートにします。

public Int32 SomeVariable { get; private set; }

次に、それを設定するには(クラスのいくつかのメソッド内から):

SomeVariable = 5;
4
Chris Shain

プライベート変数を使用し、パブリックプロパティを公開します。

class Person
{
  private string name;

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

これまでの回答は、参照型を使用しない限り有効です。それ以外の場合は、その変数の内部を操作できます。例えば:

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; }
        }
    }
}
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;
            }
        }
    }
}
Hello World!
Hello World!

3番目の例を追加した理由については、コメントを参照してください。


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

これにプロパティを使用することはできませんか?あなたがいる場合:

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

確かにネクロですが、これは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