C#中的好友类的情况

考虑以下代码模式:

// Each foo keeps a reference to its manager
class Foo
{
    private FooManager m_manager;
}

// Manager keeps a list of all foos
class FooManager
{
    private List<Foo> m_foos;
}

问题:没有办法创建一个新的Foo并更新FooManager中的m_foos列表和新的Foo实例中的m_manager引用,而不公开公开地暴露某些私有(并且冒着有人用实际的Foos使列表异化的风险)。

例如,可以在Foo中实现一个构造函数Foo(FooManager manager)。 它可以设置m_manager引用,但无法访问m_foos列表。 或者你可以在管理器中实现CreateFoo()方法。 它可以访问m_foos列表,但无法在Foo中设置m_manager。

在C ++中,显然可以声明FooManager是Foo的一个朋友来表达设计意图,但在C#中这是不可能的。 我也知道我可以让Foo成为FooManager的一个内部类来获得访问权限,但这也不是一个解决方案(如果Foo可能属于多个经理类呢?)

顺便说一句。 我知道.NET中的“内部”访问,但它要求Foo和FooManager独立存在于单独的程序集中,这是不可接受的。

任何解决方法,而不公开私人的东西?


如果我理解正确:

public abstract class FooBus
{
    protected static FooBus m_bus;
}

public sealed class Foo : FooBus
{
    private FooManager m_manager;

    public Foo(FooManager fm)
    {
        if (fm == null)
        {
            throw new ArgumentNullException("Use FooManager.CreateFoo()");
        }

        if (m_bus != fm)
        {
            throw new ArgumentException("Use FooManager.CreateFoo()");
        }

        m_manager = fm;
    }
}

public class FooManager : FooBus
{
    private List<Foo> m_foos = new List<Foo>();

    public Foo CreateFoo()
    {
        m_bus = this;
        Foo f = new Foo(this);
        m_foos.Add(f);
        m_bus = null;

        return f;
    }
}

一种选择是使用实现公共接口的Foo的私有嵌套类:

public interface IFoo
{
    // Foo's interface
}

public sealed class FooManager
{
    private readonly List<Foo> _foos = new List<Foo>();

    public IFoo CreateFoo()
    {
        var foo = new Foo(this);
        _foos.Add(foo);
        return foo;
    }

    private class Foo : IFoo
    {
        private readonly FooManager _manager;

        public Foo(FooManager manager)
        {
            _manager = manager;
        }
    }
}

由于Foo类是一个私有嵌套类,因此无法在FooManager外创建它,因此FooManager的CreateFoo()方法可确保所有内容保持同步。


你可以做的是在不同类型的命名空间中创建你的类,我们称它为“模块”(不要被类关键字愚弄,这不是真正的类):

public static partial class FooModule {

  // not visible outside this "module"
  private interface IFooSink {
    void Add(Foo foo);
  }

  public class Foo {
    private FooManager m_manager;
    public Foo(FooManager manager) {
      ((IFooSink)manager).Add(this);
      m_manager = manager;
    }
  }

  public class FooManager : IFooSink {
    private List<Foo> m_foos = new List<Foo>();
    void IFooSink.Add(Foo foo) {
      m_foos.Add(foo);
    }
  }

}

由于“模块”是分部类,因此您仍然可以在同一编译单元的其他文件中创建其他成员。

链接地址: http://www.djcxy.com/p/82179.html

上一篇: case of friend classes in C#

下一篇: Inheritance trees and protected constructors in C#