В .NET, почему я могу получить доступ к частным членам класса в классе?

Во время очистки некоторого кода, написанного сегодня кем-то другим, я изменил модификатор доступа с Public до Private на переменную class/member/field. Я ожидал длинный список ошибок компилятора, которые я использую для "рефакторинга/доработки/пересмотра" кода, который использовал эту переменную. Представьте мое удивление, когда я не получил никаких ошибок. После просмотра выясняется, что другой экземпляр класса может получить доступ к закрытым членам другого экземпляра, объявленного в классе. Полностью исключен.

Это нормально? Я кодировал в .NET с самого начала и никогда не сталкивался с этой проблемой и не читал об этом. Я, возможно, наткнулся на него раньше, но только "смутно заметил" и двинулся дальше. Может ли кто-нибудь объяснить это поведение мне? Я хотел бы знать, почему я могу это сделать. Пожалуйста, объясните, не просто скажите мне правило. Я делаю что-то неправильно? Я нашел это поведение как в С#, так и в VB.NET. Код, похоже, использует возможность доступа к закрытым переменным. Недостатком является то, что программист создал большую пластину спагетти.

С уважением,

  • Полностью запутанный

Class Jack
    Private _int As Integer
End Class
Class Foo
    Public Property Value() As Integer
        Get
            Return _int
        End Get
        Set(ByVal value As Integer)
            _int = value * 2
        End Set
    End Property
    Private _int As Integer
    Private _foo As Foo
    Private _jack As Jack
    Private _fred As Fred
    Public Sub SetPrivate()
        _foo = New Foo
        _foo.Value = 4  'what you would expect to do because _int is private
        _foo._int = 3   'TOTALLY UNEXPECTED
        _jack = New Jack
        '_jack._int = 3 'expected compile error 
        _fred = New Fred
        '_fred._int = 3 'expected compile error 
    End Sub
    Private Class Fred
        Private _int As Integer
    End Class
End Class

Ответ 1

Это "нормально". Private члены являются закрытыми для класса, а не для конкретного экземпляра.

Ответ 2

Ты сказал:

Пожалуйста, объясните, не просто скажите мне правило.

Ну, вот мои два цента.

Как я вижу, предпосылка частных членов класса заключается в том, что класс может внутренне осознавать свою собственную реализацию, не подвергая эту реализацию внешнему миру. Таким образом, один экземпляр класса отлично способен понять, как реализуется другой экземпляр того же класса; поэтому он не ограничивается использованием этих знаний о реализации.

Что касается экземпляров, которые манипулируют друг другом, я соглашусь, что это несколько необычно. Но возьмите, например, статические методы построения. Не могли бы вы также ограничить их доступ к частным членам экземпляров? Если это так, вы сделали много полезного кода невозможным. Если нет, неясно, почему статические методы должны иметь доступ к закрытым членам, но методы экземпляров не должны.

Другими словами, слово "private" в ООП не предназначено для передачи идеи личной неприкосновенности, как у людей, скрывающихся друг от друга. Скорее, подумайте о классе как о клубе "только члены", где есть определенные способы делать то, о чем знают только члены клуба.

Ответ 3

Проблема доступа - это то, где код обращается к частным членам, а не о том, к чему он обращается.

У вас есть доступ к полю _foo._int в определении класса Foo, но не за его пределами.

Еще может удивить вас тем, что следующее расширение для вложенного класса Fred также является законным.

Private Class Fred
    Private _int As Integer
    Private Sub Blah(ByVal foo As Foo)
        foo._int = 9
    End Sub
End Class

Ответ 4

Это ожидаемое поведение. Вложенные классы могут обращаться к закрытым членам класса контейнера.