Reflection是否打破了封装原则?

Sor*_*scu 10 c# oop reflection

好吧,假设我们有一个类定义的类

public class TestClass
{
    private string MyPrivateProperty { get; set; }

    // This is for testing purposes
    public string GetMyProperty()
    {
        return MyPrivateProperty;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们尝试:

TestClass t = new TestClass { MyPrivateProperty = "test" };
Run Code Online (Sandbox Code Playgroud)

TestClass.MyPrivateProperty is inaccessible due to its protection level正如预期的那样,编译失败.

尝试

TestClass t = new TestClass();
t.MyPrivateProperty = "test";
Run Code Online (Sandbox Code Playgroud)

并使用相同的消息再次编译失败.

一切都很好,直到现在,我们都在期待这一点.

但后来写道:

PropertyInfo aProp = t.GetType().GetProperty(
        "MyPrivateProperty",
        BindingFlags.NonPublic | BindingFlags.Instance);

// This works:
aProp.SetValue(t, "test", null);

// Check
Console.WriteLine(t.GetMyProperty());
Run Code Online (Sandbox Code Playgroud)

在这里,我们设法改变了一个私人领域.

仅使用反射能够改变某个物体的内部状态是不是不正常?

编辑:

感谢到目前为止的回复.对于那些说"你不必使用它"的人:那个班级设计师怎么样,看起来他再也不能承担内部的国家安全了?

Pau*_*ner 15

反射通过提供对私有字段和方法的访问来打破封装原则,但它不是第一种或唯一可以绕过封装的方式; 有人可能会争辩说,序列化会暴露一个类的所有内部数据,这些信息通常是私有的.

重要的是要理解封装只是一种技术,如果消费者同意使用您定义的API,则可以使设计行为更容易.如果有人选择使用反射或任何其他技术绕过您的API,他们就不再能保证您的对象将按照您的设计行事.如果某人为null私人领域赋予了价值,他们最好准备好在NullReferenceException下次尝试使用你的班级时抓住!

根据我的经验,编程完全是关于断言和假设.语言断言约束(类,接口,枚举),这使得创建隔离行为更容易生成,假设消费者同意不违反这些边界.

这是一个公平的断言,因为它比以前的任何技术都更容易实现软件开发的分而治之的方法.


Max*_*kin 9

反思是一种工具.你可以用它来打破封装,当它给你带来的东西比它带走的更多.

反射具有一定的"痛苦"(或成本 - 性能,可读性,代码可靠性),因此您不会将其用于常见问题.这只是更容易遵循的共同问题,这是语言的目标,通常被称为一个面向对象的原则,成功的坑.

另一方面,有一些任务在没有这种机制的情况下是无法解决的,例如使用运行时生成类型(但是,从.NET 4.0开始,它的DLR和"它将会更容易" C#4.0中的动态"变量".