6

在我最近一直在做的一些遗留 c# 代码的代码审查中,我看到了许多这样的例子:

class ManagerParentClass
{
    public string CustomProperty{get;set;}
    public void Log(string message);

    void DoABunchOfTasks()
    {
       new SomethingService().DoSomething(this);
    }
}

具有以下内容:

public class SomethingService
{
    ManagerParentClass _manager;

    void DoSomething(ManagerParentClass manager)
    {
        _manager = manager;

        // do something
        _manager.CustomProperty = "hello world";
        _manager.Log("said hello world");
    }
}

虽然这在表面上工作得很好,但我担心这有点反模式,可能会导致垃圾收集的邪恶事情。

这是否会破坏 .Net 正确清理父对象和子对象的能力中的分代垃圾收集器或其他任何负面影响?

4

2 回答 2

2

哦,是的,总的来说,这是一个可怕的反模式。我使用一个经常使用它的代码库,这简直太疯狂了。

最大的冒犯?违反封装以及随之而来的类之间的紧耦合:SomethingService对 的了解太多ManagerParentClassManagerParentClass将自己的控制权交给SomethingService.

两个更好的选择:

  1. DoSomething()一个 的实例方法ManagerParentClass,这更符合面向对象的一个​​要点:数据结构带有它们的操作符
  2. SomethingService创建一个方法,进行一些计算并返回一个值,然后调用者可以对ManagerParentClass

当然,这两种重构都涉及 的最终游戏突变ManagerParentClass,并且从函数式编程的角度来看,我会尽量避免这种情况。但如果没有更多信息,我不能为此推荐一门课程。

于 2013-06-30T03:19:31.737 回答
1

这实际上是一种将类彼此解耦的不错方式——您所写的内容看起来很像访问者模式。

您所写的示例根本没有太大的内存影响,因为除了该方法的长度之外,SomethingService 不会保留 ManagerParentClass。如果我们假设SomethingService 会在构造或常规方法期间保存这样的实例,那么它会稍微复杂一些。

让 SomethingService 持有对 ManagerParentClass 的引用意味着 ManagerParentClass 将被持有在引用中 1) 只要 SomethingService 通过一些指向 GC 根的引用链保存在内存中,以及 2) 只要​​ SomethingService 保持其对MPC。

如果 SS 要释放它的引用(将其清空),那么问题就解决了。如果 SS 本身不再被任何东西引用,那么 GC 将知道 SS 可以是 GCd,如果 MPC 仅由 SS 持有,那么 MPC 可以反过来 GCd。

于 2013-06-30T02:58:02.157 回答