c# 中不可能隐藏构造函数的嵌套类?

Posted

技术标签:

【中文标题】c# 中不可能隐藏构造函数的嵌套类?【英文标题】:Nested class with hidden constructor impossible in c#? 【发布时间】:2010-03-13 21:56:22 【问题描述】:

我最近一直在做一些编程,遇到了一个我发现在 c# 中很奇怪的问题。 (至少对我来说)

public class Foo

    //whatever
    public class FooSpecificCollection : IList<Bar>
    
         //implementation details
    
    public FooSpecificCollection GetFoosStuff()
    
         //return the collection
    

我希望 Foo 的使用者能够获得对 FooSpecificCollection 的引用,甚至对其执行一些操作。甚至可能将其设置为 Foo 或类似的其他属性,但不能创建此类的实例。 (应该能够实例化这个集合的唯一类应该是 Foo。

我的要求真的那么牵强吗?我知道人们更聪明地定义了 c#,但不应该有这样一个选项,即父类可以创建嵌套类实例,但其他人不能。

到目前为止,我创建了一个解决方案,通过属性使抽象类或接口可用,并实现在其他任何地方都不可用的具体私有类。

这是处理这种情况的正确方法吗?

【问题讨论】:

可能重复:***.com/questions/1664793/… 好奇:是否会有多个 'Foo 实例,每个实例都有自己独特的 'FooSpecificCollection ? 是的,就是这样。假设每个客户端都有一个 Foo 实例(它将由工厂在某个精确的时间创建),而 Foo 将为自己创建一个 FooSpecificCollection。我允许访问 foo 特定的集合,以便人们知道 foo 里面有什么,我让他们玩这些项目,但他们不应该能够创建一个,因为这没有什么意义。在晚上我想也许我试图让这段代码有太多的语义:) 【参考方案1】:

嵌入式类的工作方式是,它们作为外部类的成员,可以访问该外部类的私有成员。但不是相反(你想要什么)。

您可以屏蔽 FooSpecificCollection 的构造函数,但工厂必须是 FooSpecificCollection 本身的一部分。它可以招募外部类:

public class Foo

    public class FooSpecificCollection : List<Bar>
    
         private FooSpecificCollection ()    

         public static FooSpecificCollection GetFoosStuff()
         
            var collection = new FooSpecificCollection ();
            PrepareFooSpecificCollection(collection);
            return collection;            
         
    

    private static void PrepareFooSpecificCollection(FooSpecificCollection collection)
    
         //prepare the collection
    

【讨论】:

可能你是对的:)它非常类似于工厂模式(我实际上考虑过)。 总是从你的回答中学到一些东西,谢谢,Henk。在这种情况下,如果有多个 'Foo 实例会发生什么? @BillW,如果你真的要使用这种模式,你可能必须通过 GetFooStuff() 传递一个 Foo 的实例,然后再传递给 PrepareFooSpecificCollection()。【参考方案2】:

将您的嵌套类设为private,并将GetFoosStuff 的返回值设为IList&lt;Bar&gt; 而不是FooSpecificCollection

另外,deriving from List&lt;Bar&gt; is a bug 很有可能。

【讨论】:

我来自 List 而不是 foo 对不起,我的意思当然是 IList。 List 将是内部实现。但这不是问题所在。但是感谢您的警惕:) 只是好奇您所说的“从List&lt;Foo&gt; 派生是一个错误”是什么意思。我查看了链接,但找不到任何表明从 List&lt;T&gt; 派生本身存在问题的内容。 99% 的情况下,当您声称某个东西是 List 时,您实际上想说的是它是 T (IEnumerable) 的枚举。它可以工作,但是在返回类型中过于具体是糟糕的设计。【参考方案3】:

如果您正在创建一个库供其他人使用,您可以将构造函数设为internal。图书馆外的任何人都无法访问它。如果您担心在自己的项目中调用构造函数,请不要在父类之外调用它。

我们总是创建与其他类不直接相关的类,但构造函数不必对不相关的类隐藏。我们(程序员)知道这些对象是不相关的,所以我们永远不会在另一个中创建一个实例。

【讨论】:

【参考方案4】:

有一个解决方案,但我认为我不会在我的应用程序中使用它 :) 这个想法是从 FooSpecific 派生类,它是私有的,只能在 Foo 内部使用,但具有公共构造函数,因此 Foo 可以创建它的实例。

public class Foo

    //whatever
    public class FooSpecific
    
        // Protected contructor.
        protected FooSpecific()
        
        

        // All other code in here.
    

    // Private helper class used for initialization.
    private class FooSpecificInitHelper : FooSpecific
    
        public FooSpecificInitHelper()
        
        
    

    // Method in foo to create instaces of FooSpecific.
    private FooSpecific CreateFooSpecific()
    
        return new FooSpecificInitHelper();
    

【讨论】:

【参考方案5】:

不,这真的没有意义。

我的意思是,你可以潜在地返回其他实例;但是谁会从那个类派生呢?当然不是任何其他类(因为那是错误的,并且暗示它不应该隐藏在主类中),所以...

【讨论】:

我想在嵌套类中有一些功能,这些功能清晰简洁,易于阅读和使用(例如,某些 FOO 内部集合上的漂亮界面)。而且我不想让人们创建那个类。当然,无论如何他们不应该有任何业务,但我仍然想要一个明确的语义说 - 这个类可以帮助你操作一些 Foo 的东西,但是 Foo 也给了你它,你不应该自己创建它......内部在装配中是可以的,但我没有得到你的答案,为什么它没有意义。我希望使用我的类的开发人员不要尝试实例化它……为什么这毫无意义? 这里除了派生类还有其他问题。 luckyuke:所以让构造函数私有?我以为你试图阻止外部类创建它的实例。

以上是关于c# 中不可能隐藏构造函数的嵌套类?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法让构造函数只对 C# 中的父类可见?

调用 setVisible(false) 在 QWidget 的构造函数中不起作用

C# 继承和默认构造函数

在 C# 中调用类的受保护构造函数

父类的复制构造函数中的嵌套类缺少默认构造函数

超类构造函数中的虚拟化