如何在 C# 中的 class 中正确隐藏助手(内部)classes

How to correctly hide helpers (inner) classes inside a class in C#

我在理解如何正确封装我的 class 时遇到问题。它是(或者应该是)一个不可变的class。

我正在使用 "helper class",我希望它不能从外面访问。

namespace MyApp
{

    [Flags]
    public enum OctaveGroups
    {
        None = 0,
        oneOctave = 1
    }

    class Frequencies
    {
        // HelperClass
        public class Frequency
        {
            public string Name { get;  set; }
            public OctaveGroups Octave { get; set; }
        }

        public readonly static List<Frequency> All = new List<Frequency>
        {
        #region Complete Frequencies Data

                new Frequency { Name = "63", Hz = 63,
                    Octave = OctaveGroups.oneOctave | OctaveGroups.None,
                    },

                new Frequency { Name = "80", Hz = 80,
                    Octave = OctaveGroups.None,
                    }
           // And so on..
                //..

        #endregion
        };


        public readonly List<Frequency> OneOctave = All.Where(f => f.Octave.HasFlag(OctaveGroups.oneOctave)).ToList();

        public readonly List<Frequency> None = All.Where(f => f.Octave.HasFlag(OctaveGroups.None)).ToList();

    }
}

如果我将 Frequency class protectedprivate 设置为 private 我会收到此错误:

Inconsistent accessibility: field type 'List' is less accesible than field 'Frequencies.All'

如果我设置 class FrequencyList<Frequency> Allprotected 并尝试创建一个 returns 和 List<Frequency> 类似的方法,我会得到同样的错误:

public List<Frequency> GetAll()
    {
        return All.Where(f => f.Octave.HasFlag(OctaveGroups.OneOctave)).ToList();
    } 

仅公开 .All .OneOctave.None 字段同时保持只读的正确方法是什么?

正确的做法是不隐藏。

您根本无法同时向外界隐藏和暴露class。

因此,如果您想声明一个 public 返回对象或对象集合的方法,您还必须指定相关对象的类型 public。

尝试向您的频率添加一个内部构造函数 class。这将允许您从 class 内部构造一个频率,但不允许在 class 之外构造它。由于无法在外部构建,class 之外的任何人都无法将新列表添加到您的列表中,因为它们是按频率输入的。

示例:

public class ExternalType
    {
        public class InternalType
        {
            internal InternalType(string someString) 
            {
                SomeStringProp = someString;
            }

            public string SomeStringProp { get; private set; }
        }

        public readonly List<InternalType> InternalTypes = new List<InternalType>() 
        {
            new InternalType("test") 
        };
    }

如果您尝试在 ExternalType 之外实例化 InternalType,您将遇到编译器错误。但是,您的家属将能够阅读该列表。

当您计划让 public 方法返回 List<Frequency>.

时,您不能期望隐藏 Frequency

现在,我的理解是您的问题是您需要 Frequencies Frequency 中的可访问 属性 setters,但您不想公开它们到外面。这样做的方法是通过一个只暴露 getters 的接口:

public interface IFrequency
{
    string Name { get; }
    OctaveGroups Octave { get; }  
}

现在,您将 Frequencies.Frequency 设为私有嵌套 class,并且仅公开 IFrequency:

class Frequencies
{
    // HelperClass
    private class Frequency: IFrequency
    {
        public string Name { get;  set; }
        public OctaveGroups Octave { get; set; }
    }

    public readonly static List<IFrequency> All = new List<IFrequency>
    {
    #region Complete Frequencies Data

            new Frequency { Name = "63", Hz = 63,
                Octave = OctaveGroups.oneOctave | OctaveGroups.None,
                },

            new Frequency { Name = "80", Hz = 80,
                Octave = OctaveGroups.None,
                }
       // And so on..
            //..

    #endregion
    };


    public readonly List<IFrequency> OneOctave = All.Where(f => f.Octave.HasFlag(OctaveGroups.oneOctave)).ToList();

    public readonly List<IFrequency> None = All.Where(f => f.Octave.HasFlag(OctaveGroups.None)).ToList();

}

现在 Frequencies 的消费者将只能看到 IFrequency 个没有 setter 暴露的实例,因此对外界是不可变的(当然不包括反射)。