嵌套类构造函数的可见性

时间:2010-04-29 11:24:37

标签: c# constructor visibility nested-class

有没有办法限制C#中嵌套类的实例化?我想防止嵌套类从除嵌套类之外的任何其他类实例化,但允许从其他代码完全访问嵌套类。

7 个答案:

答案 0 :(得分:27)

通常我会为要向其他类公开的功能创建一个接口,然后将嵌套类设为私有并实现该接口。这样,嵌套类定义可以保持隐藏状态:

public class Outer
{
    private class Nested : IFace
    {
        public Nested(...)
        {
        }
        //interface member implementations...
    }

    public IFace GetNested()
    {
        return new Nested();
    }
}

答案 1 :(得分:6)

总之,不,你不能那样做。有一个accessibity修饰符“public”,意思是“可以通过我内部或我之外的任何东西访问”,并且有一个可访问性修饰符“private”,意思是“可以通过我内部的任何东西访问”。没有修饰符意味着“可以访问我外面的东西,但不能访问它之外的任何东西”,这就是你需要将构造函数标记为。这根本不是类型系统设计者认为有用的概念。

你能描述为什么你想要这种疯狂的可访问性吗?也许有更好的方法来获得你想要的东西。

答案 2 :(得分:5)

如果您需要满足以下要求之一:

  • 您希望密封嵌套类
  • 您不希望将所有嵌套类的方法签名复制到Lee's answer中的接口,

我找到了类似于the one posted by ak99372的解决方案,但没有使用静态初始化程序:

public class Outer
{
    private interface IPrivateFactory<T>
    {
        T CreateInstance();
    }

    public sealed class Nested
    {
        private Nested() {
            // private constructor, accessible only to the class Factory.
        }

        public class Factory : IPrivateFactory<Nested>
        {
            Nested IPrivateFactory<Nested>.CreateInstance() { return new Nested(); }
        }
    }

    public Nested GetNested() {
        // We couldn't write these lines outside of the `Outer` class.
        IPrivateFactory<Nested> factory = new Nested.Factory();
        return factory.CreateInstance();
    }
}

我们的想法是Nested类的构造函数只能由Factory类访问,该类嵌套一层。 Factory类从私有接口CreateInstance显式实现方法IPrivateFactory,这样只有那些可以看到IPrivateFactory的人才能调用CreateInstance并获取新实例Nested

Outer类之外的代码无法在不询问Nested的情况下自由创建Outer.GetNested()的实例,因为

  1. Outer.Nested的构造函数是私有的,所以他们不能直接调用它
  2. Outer.Nested.Factory可以实例化,但无法转换为IPrivateFactory,因此无法调用其CreateInstance()方法。
  3. 请注意,我不建议在生产代码中大量使用该模式,但这是一个我觉得有用的技巧,可以在极少数情况下使用。

答案 3 :(得分:3)

由于C#语法中没有任何内容,因此您必须在它们之间实现类似“契约”的内容。您可以利用嵌套类可以访问其父级的私有字段这一事实:

public class ParentClass
{
  private static Func<FriendClass> _friendContract;

  public class FriendClass
  {
      static FriendClass()
      {
          _friendContract= () => new FriendClass();
      }

      private FriendClass() { }
  }

  ///Usage
  public FriendClass MethodUse()
  {
      var fInstance = _friendContract();
      //fInstance.DoSomething();
      return fInstance;
  }
}

当然,您可以调整合约以处理不同的参数

 private static Func<Arg1,Arg2,FriendClass> _friendContract;

答案 4 :(得分:1)

对于Joshua Smith提出的答案,我发现有必要强制运行FriendClass的静态构造函数,通过从ParentClass的静态构造函数调用FriendClass上的空静态Initalize()方法来实现。

答案 5 :(得分:0)

public class Outer
{
    public class Nested
    {
        readonly Outer Outer;

        public Nested(Outer outer /* , parameters */)
        {
            Outer = outer;

            // implementation
        }

        // implementation
    }

    public Nested GetNested(/* parameters */) => new Nested(this /* , parameters */);
}

请注意,您可以从嵌套中访问Outer的私有成员。

答案 6 :(得分:-1)

更新:答案不正确,请参阅评论

您正在寻找内部修饰符:

public class OuterClass
{
    public class NestedClass {
        internal NestedClass()
        {

        }
    }
}

NestedClass对所有人都可见,但它的构造函数只对OuterClass可用。