C# 代理的封装问题?

C# 代理的封装问题?,c#,oop,encapsulation,C#,Oop,Encapsulation,我想知道为什么会这样 例如,我有一些执行器类,看起来是这样的: public class Executor { public void Execute(Action action) { action(); } } 现在我有一些需要执行的类,看起来像: public class NeedToBeExecuted { public void Invoke() { Executor executor = new Executor

我想知道为什么会这样

例如,我有一些执行器类,看起来是这样的:

public class Executor
{
    public void Execute(Action action)
    {
        action();
    }
}
现在我有一些需要执行的类,看起来像:

public class NeedToBeExecuted
{
    public void Invoke()
    {
        Executor executor = new Executor();
        executor.Execute(DoSomething);
    }

    private void DoSomething()
    {
        // do stuff private
    }
}
我的问题是为什么这是work的我将私有方法传递给其他类


这不是封装问题吗

那我试试吧

不,我们没有封装问题。您正在定义一个负责
执行
某些内容的类。
执行器
对实际执行的内容一无所知。它只知道应该执行
DoSomething
DoSomething
所做的是在负责执行某些内容的类中指定的

正如我所评论的,它与使用
线程所做的工作非常相似。您定义了一个需要在不同线程上执行的方法。这就是为什么这个类有一个线程,并定义应该在该线程上运行哪个方法。线程仍然不知道它在其中扮演角色的类

这些关系是Class=>Thread。而不是相反

在您的示例中,关系是
NeedToBeExecuted
=>
Executer
。而不是相反


这个概念对你来说可能很棘手,但你没有做错什么。

这只是一个封装问题,就像使用反射一样。使用反射可以很容易地从外部类访问私有方法和变量。你不应该认为这是一件坏事,因为它只会让语言变得更加强大。
无论如何,该类都是放弃委托方法的类,因此在某种程度上,该类正在启用该行为,因此它根本不应该是一个封装问题。

请考虑这一点:
NeedToBeExecuted
没有公开
DoSomething()
方法,它可以被任意调用,而是将其作为委托传递给另一个函数。它可以很容易地传递DoSomething()
,结果是一样的。最终,访问修饰符用于防止使用您的方法生成不同的类,您仍然可以随意使用它。如果您选择将其传递给另一个类,这是一个有效的用法。

您在方法
Invoke()
中传递
DoSomething
,并且可以在上下文中访问它。没有封装问题

但是,正如您在代码中看到的注释一样,
DoSomething
中无法访问,因此需要执行

public class Executor {
    public void Execute(Action action) {
        action();
    }
}

public class NeedToBeExecuted {
    public virtual void Invoke() {
        Executor executor=new Executor();
        executor.Execute(this.DoSomething);
    }

    private void DoSomething() {
        Console.WriteLine("I'M DOING IT MYSELF!!");
    }

    protected Executor m_Executor=new Executor();
}

public class EitherNeedToBeExecuted: NeedToBeExecuted {
    public override void Invoke() {
        // 'NeedToBeExecuted.DoSomething()' is inaccessible due to its protection level
        m_Executor.Execute(base.DoSomething);
    }
}

封装意味着能够在不更改外部代码的情况下更改某些模块的内部。这里的情况仍然如此。因此没有发生封装破坏。

不,这不是封装破坏

首先:类本身就是决定将委托分发给它的一个私有方法的对象!该类可以访问它的私有方法,如果它选择将对私有方法的引用传递给该方法的可访问域之外的代码,这完全在它的权限范围内


第二:方法的可访问域不限制调用方法的位置它限制按名称查找方法的位置。类
Executor
从不使用名称
DoSomething
来调用私有方法。它使用的名称是
action

当我们定义一个作为ThreadRunner执行的方法时,是否存在封装问题?do stuff private。。。很好,您正在将该方法作为
操作
传递。尽管它并不完全相同,但请考虑是否将私有数组或某个类实例作为参数传递给另一个方法。没什么问题
DoSomething
由于闭包,也将能够从它使用的
NeedToBeExecuted
访问私有变量。但是executer无法访问NeedToBeExecuted类的私有成员。它只接收“函数指针”。封装在这里不是问题。我觉得很有趣的是,不同的人对封装的目的有不同的看法。虽然封装确实提供了一种保险,防止依赖可能发生变化的机制的细节,但我认为封装的基本目的是让程序员能够维护其他代码可以依赖的不变量。