27
class TestClass
{
    private string _privateString = "hello";
    void ChangeData()
    {
        TestClass otherTestClass = new TestClass();
        otherTestClass._privateString = "world";
    }
}

This code compiles in C# and the equivalent works in PHP, but can someone explain the reason why otherTestClass._privateString can be changed here ?

I would have thought an instance of a class should not be able to change a private member variable under any circumstances, and that trying to access otherTestClass._privateString would give an 'inaccessible due to protection level' error.

This is not the case though, so why does instantiating an object inside its own class let you access the private members ? And should it, doesn't this break encapsulation to an extent ? Or am I missing something obvious ?

  • (I'm not asking if the above class design is good practice, just wondering about the theory behind it.)

Edit - Thanks for the answers and comments. To clarify, I'm also interested in knowing if being able to do this is regarded as a positive feature, or if it's a necessary tradeoff for better compile-time checking/code clarity/because most other languages do it that way or whatever. It seems to me ideally the compiler would prevent or warn you about this, but then I'm far from a language designer. Any examples of how it being this way lets you do something useful (without violating encapsulation) that would otherwise be difficult or impossible would be great.

Michael Low
  • 24,276
  • 16
  • 82
  • 119
  • BTW: You could make `ChangeData()` even `static` and you would still be able to access private members. – ulrichb Nov 22 '10 at 11:45
  • @ulrichb - Important to note for the OP that you can not use the `this` keyword to access private members if `ChangeData()` is `static`. – TheCloudlessSky Nov 22 '10 at 13:21
  • 1
    As an example of a language that's different - in Ruby, public is the same, but private means "only accessible by the same instance" and protected means "only accessible from the same class". Inheritance has nothing to do with it there. – Tesserex Nov 22 '10 at 13:23

2 Answers2

35

Private members are accessible to any code within the program text of that class (including within nested types). It has nothing to do with which instance of the class you're dealing with.

I don't believe this violates encapsulation - the API is still separated from the implementation, but the implementation "knows" about itself regardless of which instance it's looking at.

I believe that in some other languages this isn't how accessibility works, but it definitely is for C# and Java. (Java has slightly different rules about what can access private members, but the translated code for what you've written would still work.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    Implementing accessibility on the instance level would require a run-time check for every member variable access, whereas this model can be checked at compile time. – James Gaunt Nov 22 '10 at 11:20
  • 2
    @James: Well, not necessarily. You *could* require that private members were only ever available through the "this" reference. It would be hideous, but possible. – Jon Skeet Nov 22 '10 at 11:32
  • 1
    I'd add to Jon's answer that this type of access control allow n-ary operators such as equality to be easily written. It would be much more difficult to implement equality operator if neither instance had access to the others private members. – Andy Lowry Nov 22 '10 at 11:36
  • I agree with Andy but still think that the class level privacy has some weaknesses comparing to object level privacy. This is the reason that when I am implementing equals(Object other) in java I am using getters to obtain properties of "other" object. Obviously it is not always possible :( – AlexR Nov 22 '10 at 11:54
  • @Jon, thanks for your answer. Any chance of adding a comment about the edited-in bit part of the question too ? – Michael Low Nov 23 '10 at 04:14
  • 1
    @miket2e: Okay, a *very* simple example: it allows you to perform comparisons between two objects using private members. Basically I can't see it causing harm, and it makes life easier in terms of language complexity, compiler work, and language *use*. – Jon Skeet Nov 23 '10 at 06:22
9

This is because C# enforces class-level privacy and not object-level privacy.

Most mainstream languages enforce the same policy, i.e. C#, C++ and Java. I think the reason are:

1) because developers are accustomed to that kind of policy;

2) because object-level privacy would become much too tedious in return of very few advantages.

Simone
  • 11,655
  • 1
  • 30
  • 43
  • I don't believe there'd be the need to use "this", as compilers do are able to distinguish member variables. I think it would be tedious the need of having getter methods for each class' member value, for instance. In fact, it would go against encapsulation because you'd be exposing private members to other class too! – Simone Nov 22 '10 at 15:14
  • @miket2e Try implementing a copy constructor or a simple Equals function with object-level privacy. That simple in the current C#: return this._somePrivateField.Equals(other._somePrivateField) - if you can access other._somePrivateField, how would you implement such a feature without adding public getters? – Michael Stum Nov 23 '10 at 00:11
  • 1
    @MichaelStum: One advantage of having fields be instance-private or instance-protected is that doing so makes it clear that derived classes can re-purpose those fields without violating the Liskov Substitution Principle. Otherwise, such re-purposing may cause LSP violations. Something like `Equals` can be implemented by having a class-private `Equals` method which accepts the contents of the other object (either as a bunch of discrete parameters, or using a class-protected type), and having the public `Equals` method of an object pass its state to the `Protected` equals method of the other. – supercat Nov 29 '12 at 18:34