case of friend classes in C#
Consider the following code pattern:
// 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;
}
Problem: there is no way to create a new Foo and update both m_foos list in the FooManager, and m_manager reference in the new Foo instance without exposing some privates publicly (and running the risk of someone desyncing the list with actual Foos).
Eg one could implement a constructor Foo(FooManager manager) in Foo. It could set m_manager reference, but it has no way to access the m_foos list. Or you could implement CreateFoo() method in the manager. It can access m_foos list, but it has no way to set m_manager in Foo.
In C++, one would obviously declare FooManager a friend of Foo to express the design intent, but this is not possible in C#. I also know that I could make Foo an inner class of FooManager to gain access, but this is not a solution either (what if Foo could belong to more than one manager class?)
Btw. I know about "internal" access in .NET, but it requires that Foo and FooManager live on their own in a separate assembly, which is not acceptable.
Any workarounds for that without making private stuff public?
如果我理解正确:
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;
}
}
One option would be to use a private nested class for Foo that implements a public interface:
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;
}
}
}
As the Foo class is a private nested class, it can't be created outside the FooManager, and so FooManager's CreateFoo()
method ensures that everything stays in-sync.
What you can do is create your classes inside a different kind of namespace, let's call it a "module" (don't be fooled by the class keyword, this is not a real class):
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);
}
}
}
Since the "module" is a partial class, you can still create other members inside it in other files in the same compilation unit.
链接地址: http://www.djcxy.com/p/82180.html上一篇: 什么是私人界面?
下一篇: C#中的好友类的情况