为什么在同一类中使用构造函数参数时可以访问私有属性

3

我有一段可用的代码,但是我无法解释为什么它能够正常工作。

以这个类为例。

 public class TestClass
{
    private int _testValue;


    public void TestMethod()
    {
        var t = new TestClass() {_testValue = 42}; // Why is that working?
    }
}

为什么这是允许的? 我本以为行为会像这样:
static void Main(string[] args)
    {

        new TestClass() { _testValue = 23 }; // Does not compile and I am happy with that.

        // The code provided will print ‘Hello World’ to the console.
        // Press Ctrl+F5 (or go to Debug > Start Without Debugging) to run your app.
        Console.WriteLine("Hello World!");
        Console.ReadKey();

        // Go to http://aka.ms/dotnet-get-started-console to continue learning how to build a console app! 
    }

编辑:感谢您的评论,但我知道“private”关键字的含义,问题是,当我在同一对象内使用参数构造函数时,为什么我可以访问私有属性。

请放置一个调试器,您会发现TestClass this._testValuet._testValue不同。

在我的想法中,正常行为是在Main函数中所拥有的行为。

Debugger.


1
Main 属于哪个类?如果它与 TestClass 不同,那么您肯定无法访问 TestClass 的私有成员。但是在 TestMethod 中,您肯定可以访问。这是您的问题吗?为什么 TestClass 中的方法可以访问 TestClass 的私有成员? - MakePeaceGreatAgain
3
在类的成员内部,您可以访问private类成员。TestMethodTestClass的一个成员,因此您可以从该方法访问所有private成员。 - dymanoid
1
"this._testValue不同于t._testValue"。当然,因为您在TestMethod中创建了一个新的TestClass实例,它与当前实例(this)无关。您是否期望this指向与t相同的实例? - MakePeaceGreatAgain
2
但是为什么 this._testValue 会等于 t._testValue 呢?它们是不同的实例,因此它们的值当然不相同(除非您将它们设置为相同的值)。 - JLe
2
如果你明白这里正在做什么,真正的问题是什么?它能够这样工作是因为有人决定它应该这样工作。private表示私有于类,而不是实例。 - Lasse V. Karlsen
显示剩余4条评论
4个回答

4

private keyword
私有访问是最不宽松的访问级别。私有成员只能在声明它们的类或结构体的主体内部访问...
在类或结构体之外引用私有成员是编译时错误。

如果您查看private关键字的文档,与您的问题相关的"key"部分是它可以在类的主体内部访问,而不仅限于同一实例中声明私有成员或方法的访问。

在您添加的示例中,TestMethodTestClass中,因此TestMethod中的代码可以访问其自己的实例和任何其他实例中的任何私有方法或属性。

这在关键字的定义中指出:TestMethod位于_testValue声明的类的主体中,因此它可以访问这些内容。

文档中没有规定必须通过特定实例访问,因此无论您如何在TestMethod内创建或访问新的或不同的TestClass,都可以访问该实例的私有成员和方法。
我们使用private的原因之一是将内部内容与不相关的代码分离,但仍然提供对所属类的访问权限。这允许类操作其自身的实例,在从一个对象的一个实例复制内部数据到另一个实例时非常重要。您不希望将它们设为public,因为那样会使任何其他不相关的代码获得不需要的访问权限。 private的这种行为至少与C++和TypeScript共享,并且它可能在大多数编程语言中都具有public和private访问权限。

很抱歉,我不明白这怎么回答我的问题,我只是添加了一个调试屏幕。 - pix
@pix:答案很明确:它可以在类的主体内访问,而不仅限于同一实例的访问。 - Flater
@pix 我尝试添加一些与您展示的示例相关的进一步解释,但关键在于与“类体内”相关的定义,而不是“同一类实例内”。 - crashmstr

1

引用自文档

私有访问是最不宽松的访问级别。私有成员只能在声明它们的类或结构体的主体内部访问,例如:

-snip-

同一主体中的嵌套类型也可以访问这些私有成员。

在类或结构体外部引用私有成员是编译时错误。

至于你的屏幕截图.. 第一个 _testValue 的值为0,因为这是int类型的默认值,当你创建那个对象时没有设置其他值。

你在 TestClass 内部创建的新对象 - 你明确地将其值设置为23,这是因为根据 private 关键字的定义,你可以访问该属性。


3
我认为您需要这样做,因为它回答了您所说的问题:“为什么当我在同一个对象内使用参数构造函数时,我可以访问私有属性。”请注意,翻译保持原意,且不能包括解释或其他非翻译内容。 - Adrian
3
但是 private 关键字的定义可以回答你的问题。 - JLe
如果编辑后不能解决你的问题,那么我认为你的问题不应该反映你所假定的内容。 - Adrian
这是一个非常奇怪的行为,这是另一个例子。为什么微软或者无论你如何称呼它,都允许这种行为? - pix
@pix 在定义中已经说明了原因 :) - Adrian
@pix 我认为,这种“奇怪的行为”在许多编程语言中都很常见,如果不是所有具有publicprivate关键词的编程语言都是如此。 - crashmstr

0

让我只引用你问题的这一部分 - 我认为它应该帮助你理解这种行为:

放置一个调试器,你会发现TestClass this._testValue与t._testValue不同

现在,对于所有那些在这里发布的private关键字定义的澄清。 privateprotected访问修饰符都是指而不是对象 - 这意味着如果属性被标记为private,则该类的任何对象都可以在同一类的任何实例中访问该私有属性,包括不同的对象。这就是为什么定义明确说明:

私有成员只能在声明它们的类或结构体的主体内访问。

大多数(如果不是全部)面向对象编程语言都是如此。这样做的理由可能是,如果两个对象属于同一类,则它们知道如何正确且安全地处理和使用其私有成员 - 那么限制该访问就没有意义了。


0

你似乎假设private关心实例,但实际上它显然不关心。事实上,你甚至不需要一个实例——例如在static成员上。

因此,你能否访问类的成员取决于两个因素:

  1. 你是否在与该成员相同的作用域内?
  2. 你是否有权限访问该成员所属的实例?

在你的情况下,你的成员是private的,这使得该成员的作用域为类级别。而TestMethod是该类中的一个方法,所以第一点匹配。

你有两个不同的实例。由于你在TestMethod中,当然可以访问this(当前实例)的成员。此外,你还有一个对新创建的实例t的引用。所以第二点也适用,你可以访问两个实例的所有成员。

附带说明第2点:如果成员是静态的,则没有实例,你可以始终从另一个实例中访问它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接