为什么不能通过实例名称访问静态成员?

问题描述 投票:0回答:5

说我有:

 class Test
 {
      public static int Hello = 5;
 }

这显然有效:

 int j = Test.Hello;

但是为什么这不起作用呢?

 Test test = new Test();
 int j = test.Hello;

该实例不能有同名的成员,所以我不明白这对于编译器来说如何是不明确或无法解析的。

有人知道这是为什么吗?

编辑: 除了语言设计者出于可读性/清晰度/美观/等原因选择它之外,还有其他技术原因吗?

c# .net static
5个回答
14
投票

另一个角度:

假设这可能的。那么,当通过实例变量

null
访问静态成员时,您希望结果是什么?您想要空引用异常吗(但是为什么,因为不需要任何实例来获取静态成员)?或者您希望它起作用(在这种情况下,您会遇到奇怪的情况,即对此实例变量的某些调用起作用,但有些则不起作用)?无论哪种方式都有问题。


11
投票

记住什么是静态方法(或属性或字段):它们属于一个类,而不属于该类的任何特定实例。因此,它们在所有实例之间共享。

因此,静态成员必须通过类名而不是对象来访问是合乎逻辑的。确实,C# 语言在这方面可以进行不同的设计……但事实并非如此。


1
投票

我认为这是一种防御性语言设计:如果你错误地将一个属性声明为静态,然后当你假设它是一个实例属性时从各种实例中设置/获取它,你可能会得到各种邪恶的副作用,而不会产生任何真正的副作用。明显表明出了什么问题。

通过要求开发人员使用类名来访问静态属性,可以清楚地表明它不是实例属性,并且要求开发人员在编码时明确表示他们确实希望将其作为静态属性进行访问。


1
投票

“除了语言设计者出于可读性/清晰度/美观等原因而选择它之外,还有其他技术原因吗?”

我能想到的唯一另一个原因是,它为编译器创建了额外的障碍(这并不是一个大问题)。 如果静态方法调用可以通过实例访问,则实例必须存储所有静态偏移量,否则编译器必须执行额外的步骤,在无法调用时在类上查找具有相同签名的静态方法。在实例上找到一个非静态方法。


0
投票

您可以在 MSDN 上阅读 static 关键字的详细解释,但我认为这句话是最好的解释

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

我相信这可能会被路由到编译器使用的内存地址和偏移量中。 根据我在学校编译器课程中的记忆,实例变量的位置将存储为距存储对象的第一个内存位置的偏移量。 由于静态字段只有一份副本,因此访问静态字段的值永远不会有固定的偏移量。

关于名称的歧义,这可能就像符号表等内容中的名称冲突一样简单。 然而,很容易有更深入的技术考虑。

© www.soinside.com 2019 - 2024. All rights reserved.