【问题标题】:Nested types or other solution for one to one mapped classes一对一映射类的嵌套类型或其他解决方案
【发布时间】:2011-01-06 03:37:25
【问题描述】:

我有一个类需要以某种方式封装一些功能。

我正在考虑一个嵌套类,并将该功能和一些状态放入其中。 这两个类之间的关系是一对一的。

访问外部类成员变量或方法的问题应该声明为static,我不想要它。另一种解决方案是将外部类的引用传递给内部类。

解决我的问题的最佳做法是什么?

【问题讨论】:

  • 你能告诉我们你到目前为止有什么吗?
  • 内部类是一种处理外部类数据的数据处理类。我需要访问外部类的所有内容,但仍以某种方式封装。也许将此功能定义为一个新类并不是一个好主意。

标签: c# class nested one-to-one


【解决方案1】:

虽然我不会说嵌套类是邪恶的,但它们肯定是“恶作剧”,嵌套类可以解决的问题很少,不能以不同的方式或更优雅地解决.

所以这真的取决于你的具体情况,但需要考虑的一些事情是:

  1. 嵌套类是否公开可见?由于消费者必须使用语法来引用嵌套类型,因此它们很笨拙:OuterType+InnerType

  2. 平均而言,源文件变得更大,并且更难阅读和推理(尽管战略性地使用部分类可以缓解这种情况)。

  3. Visual Studio 中的代码分析会大声抱怨公共嵌套类(框架设计指南人员认为它们不是良好的形式),因此如果您使用 FxCop,则需要进行例外处理。

如果您发布更多细节,我们或许可以提供更详细的指导。

【讨论】:

  • 我的场景很复杂,如果我把它带到这里,可能没有人会读到这样的问题。我尽可能地简化了这个概念。如何封装一组功能同时又可以访问所有的原始类?
  • 对,但是“封装一组功能”是面向对象设计的精髓,当然也不需要要求使用嵌套类。一般而言,单一职责原则会建议将此类功能“封装”起来,并将其与其他未来变化的原因“分开”。我认为一些细节会真正阐明您在这里面临的问题。
【解决方案2】:

大约 6 个月前,我们遇到了完全相同的问题,但原因不同。我们有大约 20 个“常规”类和一个巨大的木星大小的类,它们做得太多了,需要分解。

我们实际上需要两个孩子,除了父母,两个孩子都与父母是一对一的关系。

第一次尝试(确实有效)使用了老式模式,即在每个孩子的构造函数中传递“this”的引用,然后使用 .Parent 方法向上导航。由于 GC 问题,这是一场噩梦,我们在短时间内寻找了更好的解决方案。

最好的解决方案(今天仍在使用)是在需要查询父级的子级方法中简单地接受父级类类型的引用。这工作得非常好,GC 喜欢它,并且一切都按预期实例化和释放。代码更易于管理,更有条理,我们现在真的很高兴我们投入了时间来完成它。

所以,这是我的建议:

Parent
 |
 +-Child1
 |
 +-Child2

子对象的方法只在需要它的方法中接受对父类的引用。

它实际上很像 ADO.Net 的开发方式,独立的对象在需要的方法中接受彼此的引用。

【讨论】:

  • 非常感谢。我正在考虑在构造函数中传递父级的引用。我认为GC 问题不应该发生,如果两个孩子都已完成,那么你也可以处置父母。 GC 在他想要的时候做(处置),除非有特殊情况,否则这很好。在这种情况下,您可以强制 GC 执行此操作(GC.Collect() 但这是性能杀手)。我将添加另一个解决方案作为答案,但我不知道它是否是已知模式、最佳实践......或不是!
  • 其实在构造函数中传递父级的引用应该没有问题。问题是当子级将引用存储回父级时的循环引用 .Parent 属性。我们希望 GC 会看到对这两个对象的唯一引用是彼此的,但事实并非如此。无论如何,如果你不做 .Parent 属性,在构造函数中传递父级应该没问题。
【解决方案3】:
using System;

class OuterType
{
    private static OuterType _instance;

    public OuterType()
    {
        _instance = this;
    }

    private String Message
    {
        get { return "Hello from OuterType"; }
    }

    public void testInnerType()
    {
        InnerType innerType = new InnerType();
        Console.WriteLine(innerType.FormattedOutertMessage);
    }

    private class InnerType
    {
        private readonly OuterType _outerType = _instance;

        public String FormattedOutertMessage
        {
            get { return _outerType.Message.ToUpper(); }
        }
        // InnerType doesn't need to dispose any object of OuterType.
    }
}

然后它是这样工作的:

class Program
{
    static void Main(string[] args)
    {
        OuterType outerType = new OuterType();
        outerType.testInnerType();
        Console.ReadKey();
    }
}

但我不确定这是否是个好主意?!

【讨论】:

    猜你喜欢
    • 2015-08-05
    • 2021-12-11
    • 2017-05-25
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多