代码之家  ›  专栏  ›  技术社区  ›  Loren Pechtel

C,如何处理常量表

  •  7
  • Loren Pechtel  · 技术社区  · 15 年前

    奇怪的是,语言显然没有合适的功能。

    我发现我自己的数据最好用多维数组来表示,但它是绝对不变的,任何人都无法在不改变相关代码的情况下改变它。面对Delphi中的这些东西,答案是显而易见的——一个常量,其值就是表。然而,C似乎不支持这样的事情。

    谷歌让很多人抱怨这一点,没有很好的答案。

    人们如何处理这种情况?

    (不要说常量不属于代码中——我最后一次碰到的是所有可能的4项排列。除非时空的本质发生了改变,否则这是一成不变的。)

    怎么搞的?有一个非常接近的答案,我问了一个细节,它就消失了!简单地声明一个数组就完成了这项工作——唯一的问题是每次都要运行数组分配。我前面的那个包含96个值——如何让它只初始化一次?我是否只需要接受范围远远超出它应该接受的范围?(就目前情况而言,它是在一个三行程序中,相当于一个O(n^3)程序。)

    6 回复  |  直到 15 年前
        1
  •  2
  •   Reed Copsey    15 年前

    里面有一页 C# FAQ 关于这件事。

    他们建议使用静态只读数组:

    static readonly int[,] constIntArray = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }};
    

    但是,请注意,这只是一种常量,您仍然可以重新分配数组中的单个元素。另外,这必须在类级别上指定,因为它是静态的,但是它可以很好地工作。

        2
  •  3
  •   recursive    15 年前
        3
  •  1
  •   Douglas    15 年前

    可以使用只读哈希表。唯一的缺点是readonly不会阻止您更改哈希表中特定项的值。所以它不是真正的常量。

    readonly Hashtable table = new Hashtable(){{1,"One"},{2,"Two"}};
    

    或数组

    public readonly string[,] arry = new string[,]{{"1","2"},{"2","4"}};
    

    是的,您需要在适当的范围内声明变量,这样它就不会被多次初始化。

        4
  •  1
  •   Robert Paulson    15 年前

    喜欢 他们 比如,添加另一层间接性。C不需要提供专门的数据结构作为语言原语,尽管有时人们希望有一种方法可以使任何类不可变,但这是另一种讨论。

    现在你没有提到是否需要在那里存储不同的东西。事实上,除了多维之外,您没有提到任何其他内容,也没有能力更改值或数组。我甚至不知道访问模式(单个int、int、int索引器)是否合适。

    但一般来说,对于一个三维锯齿状数组,以下是可行的(但它并不漂亮)。

    一个警告是,您使用的构造类型也需要是不可变的,但这是您的问题。您可以创建自己的只读包装器。

    public static readonly ReadOnlyThreeDimensions<int> MyGlobalThree 
        = new ReadOnlyThreeDimensions<int>(IntInitializer);
    
    public class ReadOnlyThreeDimensions<T> 
    {
        private T[][][] _arrayOfT;
    
        public ReadOnlyThreeDimensions(Func<T[][][]> initializer)
        {
            _arrayOfT = initializer();
        }
    
        public ReadOnlyThreeDimensions(T[][][] arrayOfT)
        {
            _arrayOfT = arrayOfT;
        }
    
        public T this [int x, int y, int z]
        {
            get 
            {
                return _arrayOfT[x][y][z];
            } 
        }
    }
    

    然后您只需要提供一些初始值设定项方法,或者在静态构造函数中分配它。

    public static int[][][] IntInitializer()
    {
        return xyz // something that constructs a [][][]  
    }
    
        5
  •  0
  •   Peter Wone    15 年前

    当然是列举。

        6
  •  0
  •   csharptest.net    15 年前

    好吧,我采取了下面的方法,读起来有点讨厌,但编辑起来很容易。

        public struct Something
        {
            public readonly int Number;
            public readonly string Name;
            public Something(int num, string name) { this.Number = num; this.Name = name; }
        }
    
        public readonly Something[] GlobalCollection = new Something[] 
        {
            new Something(1, "One"),
            new Something(2, "Two"),
        };