【问题标题】:instance of a class and derived classes can change a static member of the class indirectly through a non-static method in c#类和派生类的实例可以通过c#中的非静态方法间接更改类的静态成员
【发布时间】:2026-01-26 03:05:02
【问题描述】:
public class Class1
{
  public static string Name="foo";

  public void ChangeName(string _name)
  {
    Name=_name;
  }
}

in some other class..

Class1 _c=new Class1();
_c.ChangeName("bar");

并且名称被更改.. 更改静态成员的实例!

我认为静态成员仅适用于类。如果一个类想要它可以改变它的静态成员。 但是这里一个实例是可以间接改变它的。不应该一个实例不能改变它吗?当我们创建一个实例时,它在堆中占据自己的空间,而无法访问类的静态成员。那么这里到底发生了什么?

【问题讨论】:

  • 您如何想象所有外部组件能够更改静态变量并消除类实例的可能性?
  • 这是一个多线程的噩梦。 ;)
  • 这不是像房屋(实例)一样决定蓝图(房屋类)以及其他实例的命运吗?如果蓝图想要它可以改变自己,那么根据这个新蓝图创建的房屋就会受到影响。不是一所房子决定其他房子的外观。这不是重点吗??
  • 我认为它是这样的......蓝图赋予了房子改变蓝图本身的能力。

标签: c# .net oop static


【解决方案1】:

重要的是

public static string Name="foo";

创建一个可变静态属性。这允许

Class1.Name="bar"

从类的外部以及从类的内部 - 在类内部,您可以将其缩短为

Name="bar"

这正是通过ChangeName("bar")调用的内容

你可以考虑

public static readonly string Name="foo";

编辑

如果您希望只能从静态方法中更改值,请考虑使用具有适当设置器逻辑的设置器/获取器构造。

【讨论】:

  • 但我希望一个类能够多次更改其静态成员!如果它是只读的就不能这样做
  • 那么,有什么问题呢?如果您可以更改您的类静态属性,您也可以从类中更改它 - 例如在您的 OQ 代码中。
【解决方案2】:

不,不会阻止实例访问静态成员。实例彼此分离,但静态成员对静态方法和实例方法都可用。

由于您已将其公开,因此甚至不仅是类本身的方法可以访问它。您可以从任何地方更改它:

in some other class...

Class1.Name = "Albert";

【讨论】:

  • 实例方法不应该只能“获取”那些静态成员而不是“设置”它们。我知道这就是它的发生方式,但这不是一件坏事。从我上面的评论来看这个场景怎么样:它不是像房子(实例)一样决定蓝图(房子类)以及其他实例的命运吗?如果蓝图想要它可以改变自己,那么根据这个新蓝图创建的房屋就会受到影响。不是一所房子决定其他房子的外观
  • @suyash:静态成员根本不是蓝图的一部分,它们就像一个社区建筑,可供所有实例使用,并由所有实例共享。不要试图将静态成员视为面向对象原则的一部分。它们受访问修饰符的影响,但根本不参与继承。
  • 这是有道理的。但我仍然想不出一个对象如何决定其他兄弟姐妹的命运的场景(访问应该只是获取而不是设置)。顺便说一句,如果一个类有一个公共静态成员,它可以通过派生类访问。这增加了我的问题..为什么对象和派生类能够更改父类的静态成员。
  • @suyash:派生类的实例可以像其他任何地方的任何其他代码一样更改静态成员。唯一的区别是您不必指定类名,即您可以使用Name = "foo"; 而不是Class1.Name = "foo";。要控制谁可以设置成员,可以使用属性而不是变量,然后可以将 setter 设为私有:public static string Name { get; private set; }。但是,如果您保留 ChangeName 方法,则可以在任何地方使用它来更改属性,因为它会在其自身的访问限制之外公开属性。
【解决方案3】:

MSDN 明确指出:

“虽然一个类的实例包含该类所有实例字段的单独副本,但每个静态字段只有一个副本。”

【讨论】: