C# 公共变量在类内可写,但在类外只读

发布于 2024-10-11 15:50:06 字数 79 浏览 5 评论 0原文

我有一个 .Net C# 类,我需要将变量公开。我需要在方法中(而不是在构造函数中)初始化此变量。但是,我不希望其他类可以修改该变量。这可能吗?

I have a .Net C# class where I need to make a variable public. I need to initialize this variable within a method (not within the constructor). However, I don't want the variable to be modifieable by other classes. Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

温馨耳语 2024-10-18 15:50:06

不要使用字段 - 使用属性:

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

Don't use a field - use a property:

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

In this example Foo.Bar is readable everywhere and writable only by members of Foo itself.

As a side note, this example is using a C# feature introduced in version 3 called automatically implemented properties. This is syntactical sugar that the compiler will transform into a regular property that has a private backing field like this:

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;
        }
    }
}
疯了 2024-10-18 15:50:06
public class Foo
{
  public string Bar { get; private set; } 
}
public class Foo
{
  public string Bar { get; private set; } 
}
想挽留 2024-10-18 15:50:06

为此,您必须使用属性。如果您对自动 getter/setter 实现感到满意,那么这将起作用:

public string SomeProperty { get; private set; }

请注意,无论如何您都不应该将字段公开为公共字段,除非在某些有限的情况下。请改用属性。

You have to use a property for this. If you are fine with an automatic getter/setter implementation, this will work:

public string SomeProperty { get; private set; }

Note that you should not expose fields as public anyway, except in some limited circumstances. Use a property instead.

狼亦尘 2024-10-18 15:50:06

当然。将其设置为属性,并将 setter 设置为私有:

public Int32 SomeVariable { get; private set; }

然后设置它(从类中的某个方法中):

SomeVariable = 5;

Sure. Make it a property, and make the setter private:

public Int32 SomeVariable { get; private set; }

Then to set it (from within some method in the class):

SomeVariable = 5;
两个我 2024-10-18 15:50:06

使用私有变量并公开公共属性。

class Person
{
  private string name;

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

Use a private variable and expose a public property.

class Person
{
  private string name;

  public string Name
  {
    get
    {
      return name;
    }
  }
}
一枫情书 2024-10-18 15:50:06

您不允许为此使用财产吗?如果您是:

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

Are you not allowed to use a property for this? If you are:

private string _variable
public string Variable {
    get {
        return _variable;
    }
}
征棹 2024-10-18 15:50:06

只要您不使用引用类型,到目前为止的答案就很好用。否则,您仍然可以操纵该变量的内部结构。
例如:

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

The answers so far work good as long as you dont use reference types. Otherwise you will still be able to manipulate the internals of that variable.
e.g:

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!

Which may be exactly what you want as you wont be able to change SomeBar but if you want to make the internals of the variable unmodifiable you need to pass back a copy of the variable, e.g.:


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!

See comments for why I added the third example:


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

走过海棠暮 2024-10-18 15:50:06

Necro 当然可以,但这还不用说 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; private set; } = String.Empty;

    }

Necro for sure, but this bares mentioning with the improvements to the language 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; private set; } = String.Empty;

    }
云裳 2024-10-18 15:50:06

将其定义为私有?这就是您所要求的,您可以在容器类内的任何位置修改它,但不能在它之外

Define it as private? Is that what you asking for, you can modify it any where inside the container class but you can't out side it

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文