Why is it even possible to change a private member, or run a private method in C# using reflection?

C#.NetReflection

C# Problem Overview


I recently came across a problem that I was having using C#, and it was solved by setting a private member using reflection.

I was stunned to find out that setting a private member/field and also running a private method are things that are allowed and possible in C#. This is not a question of how to do these things, they are well documented, my question is: why?

If you set a field/member/method as private/internal, why would C# as a language allow these fields to be set outside the scope? I would think that this would throw an exception of some kind. If the class wanted them to be changed or set wouldn't there be a method or a constructor?

C# Solutions


Solution 1 - C#

Because the access modifiers are there to assist with documenting the API that you want to expose to consumers, or to inheritors, etc.

They're not a security/access control mechanism.

Solution 2 - C#

It's impossible to prevent someone from being able to do that. You could make it harder, you could force them to use unsafe code and start setting bits around blindly. After all, it's their program/machine, they're allowed to do such things.

The design of the language is such that it makes it hard for you to shoot yourself in the foot and do Bad Things. But it doesn't make them impossible, doing so would also restrict users from doing things that are unusual, but still desirable.

Solution 3 - C#

Private reflection requires that you be granted essentially full trust. Full trust means full trust. If you're fully trusted to be doing the right thing then why shouldn't that work?

(In fact, the security model for private reflection is actually much more complicated than I've sketched it here, but that does not affect my point: that this ability is subject to policy. See Security Considerations for Reflection (MSDN) for an overview of how reflection and security policy interact.)

Solution 4 - C#

Visibility modifiers aren't meant for security.

They are simply meant to make working with structured API's/codebases more effective - as to not bog the programmer down with guff - and only expose the things that consumers should be concerned with.

Solution 5 - C#

Reflection is how you interact with compiled code. If reflection respected the source language's expectations about privacy, there would be a need for another mechanism just like it which didn't. Turtles all the way down.

Start by assuming that what it does is what it's meant to, then re-evaluate your assumption that it was a misguided effort to do something different that nobody wants to do anyway.

Solution 6 - C#

Sometimes, you have to cheat.

It's easy to say that the class should have a setter for something if it needs to be set, but what if you can't add one? What if it's not your class, it's a proprietary library and you need to work around a bug in it? I'm not saying that you should do such things, in fact I would say that you almost certainly shouldn't, but sometimes the only way to get something to work is outrageous cheating. In those cases, the fact that these mechanisms exist is extremely helpful.

You should, however, always question their use, and of course be aware that violating the public API of an object is likely to cause you problems further down the line and is probably the wrong thing to do. Except in the aforementioned scenario when it's the only way you can make something work in some code that you don't have the ability to change.

One thing to note is that C++ and its derivatives have strong access control, but there are a lot of OOP languages that don't. Perl 5 objects, for example, are entirely open to outside interference, and private methods and data are only there by convention - a Perl programmer knows that messing about inside a third-party object's hashref is probably going to break things, so they generally won't do that. Again as with C#'s reflection capabilities though, sometimes you can solve an awful lot of problems with a little tweak to something you're not really supposed to touch.

But I reiterate yet another time, you almost certainly shouldn't do it. These capabilities are not intended for everyday use.

Solution 7 - C#

I cannot even see my face without through something reflective. Okay, I can watch myself in a video, but that is done by the optical device called a camera, and it's also something use the technique of reflection.

If I were sick, I possibly would already be dead when doctors need X-rays to diagnose and treat my illness, but all kinds of reflections are unable to see what is private of me. And I can never see myself neither.

The X-ray (or something tomography-like) can watch the inside of me, what I can never do without it.

1kUml.jpg

I'd rather say it's more realistic than reflection. But yes, I cannot use my eyes to see the real me directly, every me that I've ever seen, were some kind of reflection. (To think it in depth, eyes also give us the reflection of reality.)

So, reflection is supposed to related to realistic, without a particular view. And you can assume that the consumers code is restricted to BindingFlags.Public, within the rules of object-orientation.

In the real universe, almost nothing is impossible; the only difference between possible and impossible to us, is whether it can done by human, since we are human beings.

It seems dangerous that reflection can do everything in the universe of programs, and now it's required to be fully trusted for the security reason, in a human's logic.

Solution 8 - C#

Good question.

My answer would be: Access modifiers and visibility are part of the API design. With reflection, you have full control over pretty much everything, including bypassing the API and modifying data on the low level.

Access modifiers can make your classes safe from accidental changes from the outside. You can call a method or access a public member "by accident". With reflection, it is hard to maintain that you did things by accident.

And if this low level access on reflection were NOT possible, a lot of stuff that we all have come to know and like would be virtually impossible.

Solution 9 - C#

A case in production code:

We wanted one web service to work in the NZ timezone. Probably the correct solution is to rewrite all our code (including some .NET Framework serialization code) to use DateTimeOffset, but the simplest solution was effectively to adjust the two private fields in the .NET Framework that store the current timezone (normally based upon registry calls) to use the NZ timezone explicitly.

We know that if the .NET Framework version 2.0 is ever updated in its handling of time zones we may have to rework our code, but for the moment this is working fine in production.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRyan DrostView Question on Stackoverflow
Solution 1 - C#Damien_The_UnbelieverView Answer on Stackoverflow
Solution 2 - C#ServyView Answer on Stackoverflow
Solution 3 - C#Eric LippertView Answer on Stackoverflow
Solution 4 - C#Dave BishView Answer on Stackoverflow
Solution 5 - C#15ee8f99-57ff-4f92-890c-b56153View Answer on Stackoverflow
Solution 6 - C#Matthew WaltonView Answer on Stackoverflow
Solution 7 - C#Ken KinView Answer on Stackoverflow
Solution 8 - C#Jan DörrenhausView Answer on Stackoverflow
Solution 9 - C#Mark HurdView Answer on Stackoverflow