Version Used:
C# 9 (Possibly prior versions too. Will require more testing.
Steps to Reproduce:
namespace TestBrokenEncapsulation
{
public class TestClass1
{
string x = "abc";
public void test(TestClass1 a)
{
a.x = "hjk";
}
}
class Program
{
static void Main(string[] args)
{
TestClass1 x = new TestClass1();
TestClass1 y = new TestClass1();
Console.WriteLine($"Before:: x.x={x.getX()} and y.x={y.getX()}");
x.test(y);
Console.WriteLine($"After:: x.x={x.getX()} and y.x={y.getX()}");
}
}
}
Expected Behavior:
Should error out due to encapsulation being broken.
Actual Behavior:
Breaks encapsulation.
This behavior is correct according to the specification, so I don't think there's anything to fix here.
As I understand it, encapsulation is not about isolating objects from each other, it's about isolating parts of your program from each other. That way, you can know that only code in this class can use its private members, which in turn makes it easier to ensure your code is correct or to refactor it. Preventing access to other instances of the same type wouldn't help with that, but it would make some common patterns harder to express.
Ok given that it is by spec/design. How about giving a special new access modifier that isolates one object instance from corrupting/modifying another object instance of the same class. While many things are the law they might not necessarily be good at all :P.
The spec states:: "If the declared accessibility of M is private, the accessibility domain of M is the program text of T."
Which is fine but this is a limited subset of the general concept of encapsulation.
Since you want to talk semantics I will leave nothing to the imagination to prevent more unnecessary flames.
The general purpose of encapsulation is to protect a an object instances private variables from other external object instances, regardless of same type or not, from changing its data to protect from corruption.
The specification's/design's very limited definition, subset of the general concept of encapsulation, to only program text is fine technically by the specification/design.
2 paths:
1) Change the spec.
2) Create a higher level of encapsulation like "private instance" access modifier or whatever buzz word you want to come up with.
In closing this is a problem as it can lead to trouble very easily. This does not require some fancy hacking detailed over complicated very limited case code. If you want to keep people from harming themselves and saving time debugging trying to find how a classes private data, property, was changed magically you should do something about it.
Thank you @huoyaoyuan. Good someone noticed this horrible design problem.
I do not have such problems in my code as I never code like this.
Just wanted to help the others who follow processes and do not understand.
Cheers.
Closing issue.
Upon looking more into dotnet/csharplang#2718 it is different as it is a suggestion. This issue is a design problem/bug. I am not filing as issue dotnet/csharplang#2718 for a design suggestion but as a design bug/problem.
Reopening the issue until senior people close it by themselves.
Cheers. Peace out I have done my good deed. All yours @MadsTorgersen
Also @MadsTorgersen if this goes into the CLR then I am willing to do the typing labor of refiling the issue there if you will kindly help me out by posting a link to the correct issue list. Thanks in advance.
Also it is not a good idea to bypass property getters and setters in foreign objects which hold different references to resources with code based sanity checks. I can list lots of problems due to this issue.
it is different as it is a suggestion. This issue is a design problem/bug.
It was an issue. It's converted into discussion because people didn't get agreement.
This fall in the scope of custom analyzer. For private members, all the usage must be through source, not metadata. There can be an analyzer finding [InstancePrivateAttribute], and reporting error for misusage.
Per discussion in dotnet/csharplang#2718 , people don't think this is a big problem in practice. You can share your thoughts, but don't just say 'it's should be implemented' just based on your opinion.
Finally, don't tag the language designer in such a way. They will take decision based on the discussions in the csharplang repo.
I'd suggest you to go to dotnet/csharplang#2718 , and talk about what problem you've met without this feature.
I did not say it should be implemented. I do not make decisions. I pointed out a bug. Again I understand that the community feels and the program manager does too that this does not require fixing which is your decision to make.
I said something should be done about it. Which it seems to be done already that this is a non-issue and will stay this way which is again your decision to make.
Finally why tag a manager or potential decision maker::
I get unsatisfactory answers then I escalate to the manager who can close, delete my request at all.
Hypothetically if there are plans to say push to compete for C# to be used in mission critical systems this could lead to crashes.
A potential hypothetical crash scenario, by mistake of course, in say a hypothetical medical (life or death) embedded system that has low resources where one would use unmanaged code.
What if, again hypothetical, said unmanaged code is using a private variable outside its scope or passed in indirectly and that is again hypothetically and accidentally cleared or corrupted?
Would you consider such a Use Case as acceptable?
Would you think something should be done about it?
This is all I am saying. What you have decided to do is up to you as I have no control or say over it. All I can do is flag it, post it.
I am only trying to report a bug/problem issue. I am not part of the team. I am merely a user of C#.
Again I apologize for any and all perceived trouble I have caused which was not my intent at all.
Unlike the dead article from 1 year ago I have supplied simple code that shows the bug problem. So I do not want to waste my time with that suggestion issue thread. There is nothing for me to discuss. The code is there showing the problem. You decide what you want to do.
I pointed out a bug.
There's nothing bug. private was designed to be 'class' not 'instance' since the first version, and so does C++, so does Java. It just doesn't fit your expectation.
Closing out as by design. If you'd like to start a discussion about a way to make this sort of thing impossible, feel free.
Note: class-based encapsulation is extremely prevalent. This has been how this (and many other languages) have worked since their origin. If you want to make this not allowed, you'll have to work very hard to convince people that this perspective has merit.
Unlike the dead article from 1 year ago I have supplied simple code that shows the bug problem.
You show one instance able to mutate another instance of the same type. This does not seem like a problem/bug. Indeed, that's exactly the definition of what private means
Will do.
Thanks for making a decision and closing it.
Good to know this is prevalent across all languages.
Can be useful as a feature too to change private data when needed.
If possible, @CyrusNajmabadi, can you please talk to the documentation people and close the original issue I first raised which came about by reading the C# documentation. Asking this since you have authority to close out issues.
I will post that there too. As this issue was addressed differently and not dismissed so there seems to be a communication gap between you and your documentation team.