You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#类间依赖设计合理性及IDisposable实现相关疑问

PersonFinder与Person类设计问题解答

示例代码

PersonFinder类(A类)

public class PersonFinder
{
    // 为简化逻辑,假设每个人的名字唯一
    public Person FindPersonByName(string name)
    {
        // 查找逻辑省略
        return new Person(name, this);
    }
}

Person类(B类)

public class Person
{
    public string Name { get; set; }
    private string childName { get; set; } // 简化假设:每个人都知道自己孩子的名字
    private PersonFinder _personFinder { get; set; }

    public Person(string name, PersonFinder personFinder)
    {
        Name = name;
        _personFinder = personFinder;
    }

    public Person GetChild()
    {
        return _personFinder.FindPersonByName(childName);
    }
}

问题1:该设计是否合理?有无更优实现方式?

现有设计的合理性

这个设计基本符合单一职责原则:把Person对象的查找/创建逻辑集中在PersonFinder类,Person只负责自身核心业务逻辑(比如获取子对象),不用关心对象查找细节,一定程度上降低了Person类的复杂度。

但存在明显缺陷:

  1. 重复创建对象:每次调用FindPersonByName都会生成新的Person实例,即使同一个名字被多次查找,也会产生重复对象,既浪费内存又可能导致数据不一致。
  2. 耦合过紧:Person直接依赖PersonFinder具体类而非抽象接口,后续如果要替换查找逻辑(比如从数据库查询改成缓存查询),必须修改Person类代码,违反了依赖倒置原则。

更优实现方案

  1. 添加对象缓存:在PersonFinder中维护字典缓存已创建的Person实例,避免重复创建:
public class PersonFinder
{
    private readonly Dictionary<string, Person> _personCache = new Dictionary<string, Person>();

    public Person FindPersonByName(string name)
    {
        if (_personCache.TryGetValue(name, out var existingPerson))
        {
            return existingPerson;
        }
        var newPerson = new Person(name, this);
        _personCache.Add(name, newPerson);
        return newPerson;
    }
}
  1. 抽象查找接口:定义IPersonFinder接口,Person依赖接口而非具体类,提升扩展性:
public interface IPersonFinder
{
    Person FindPersonByName(string name);
}

public class PersonFinder : IPersonFinder
{
    // 缓存实现同上
}

public class Person
{
    private readonly IPersonFinder _personFinder;

    public Person(string name, IPersonFinder personFinder)
    {
        Name = name;
        _personFinder = personFinder;
    }

    // GetChild方法逻辑不变
}
  1. 优化子对象关联:如果childName需要从外部数据源获取,可在Person构造时直接注入,或者由PersonFinder在创建Person时一并初始化,避免Person类持有未明确初始化的字段。

问题2:若PersonFinder实现了IDisposable,Person类是否需要实现?

Person类不需要实现IDisposable,这并非规则例外,而是对微软IDisposable规则的正确理解:

微软文档的核心规则是:当类拥有IDisposable对象的所有权时,才需要实现IDisposable。这里的“所有权”指该类负责创建对象,或承担其生命周期管理责任(比如决定对象何时释放)。

在你的场景中,PersonFinder是全局共享的唯一实例,其生命周期由上层应用(比如程序启动/退出逻辑)管理,Person类只是持有引用并使用,并不拥有它的所有权。如果Person实现Dispose并释放PersonFinder,会导致其他正在使用该实例的Person对象出现错误(共享实例被提前销毁)。

正确做法是:由创建PersonFinder的上层代码负责调用其Dispose方法,Person类无需处理。


内容的提问来源于stack exchange,提问作者Ramon Thomaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:42:45