如何在C#中创建一个索引从1开始的一维数组

Pet*_*uer 14 c# arrays indexing

对于多维数组,Array.CreateInstance可用于创建基于非零索引的数组,但如果您尝试使用1维数组(向量),例如:

public double[] myArray = (double[])Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });
Run Code Online (Sandbox Code Playgroud)

当从多维数组转换为单维数组失败时,这将在运行时失败

"Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'"
Run Code Online (Sandbox Code Playgroud)

现在我可以创建一个基于零的数组并忽略第一个值,或者使用偏移等,但我是否忽略了一些允许基于非零的向量的c#语法魔法?

更新:

我要埃里克利珀如果他说的话吧' 有做一个非零基于C#阵列没有明显的方式

Jef*_*dge 25

你可以在C#中创建一个非零的数组,但它的使用是有点令人讨厌的.它绝对不是普通(即,基于零的单维)阵列的简单替代品.

        // Create the array.
        Array myArray = Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });

        // Fill the array with random values.
        Random rand = new Random();
        for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
        {
            myArray.SetValue(rand.NextDouble(), index);
        }

        // Display the values.
        for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
        {
            Console.WriteLine("myArray[{0}] = {1}", index, myArray.GetValue(index));
        }
Run Code Online (Sandbox Code Playgroud)

为此所需的GetValue/SetValue语法比在每次出现时从向量索引中减去一个语法更加丑陋.

如果值类型存储在数组中,那么它将存储在连续位置,就像在常规数组中一样,但是getter和setter将需要装箱值(除非有一些我不知道的编译器魔法) .吸气剂通常需要一个演员(只是为了使它更加丑陋).

    double myValue = (double)myArray.GetValue(index);
Run Code Online (Sandbox Code Playgroud)

还要注意正确的比较GetUpperBound<=,Length与之不同的是<.


mik*_*ike 14

基于非零的数组DO存在于C中,并且有一种方法可以创建基于1(或其他)的数组.

我完全同意它们是混乱的,并且它们不应该用于除遗留内容之外的任何东西,但它们与旧的COM库交互是必不可少的.

遇到这种情况最常见的地方是使用Excel库中的Microsoft.Office.Interop.Excel.Range对象,该对象仍然使用下面的旧DCOM接口.

例:

/// <summary>
    /// Makes the equivalent of a local Excel range that can be populated 
    ///  without leaving .net
    /// </summary>
    /// <param name="iRows">number of rows in the table</param>
    /// <param name="iCols">number of columns in the table</param>
    /// <returns>a 1's based, 2 dimensional object array which can put back to Excel in one DCOM call.</returns>
    public static object[,] NewObjectArray(int iRows, int iCols)
    {

        int[] aiLowerBounds = new int[] { 1, 1 };
        int[] aiLengths = new int[] { iRows, iCols};

        return (object[,])Array.CreateInstance(typeof(object), aiLengths, aiLowerBounds);

    }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,这个代码是必要的原因是每个DCOM调用excel是一个跨进程调用,如果你一次一个地访问单元格,你会产生巨大的开销,(检索或设置)值).Excel范围是基于1的2维数组,如果创建数组并在本地填充数组,则可以将其推送到一个跨进程调用中,从而创建巨大的性能提升.

  • 谢谢,Excel正是我现在遇到这个问题的地方. (3认同)

Gen*_*eev -7

C# 中的所有数组都是从零开始的。据我所知,没有办法创建一个基于 1 的数组。想象一下,如果可能的话,会发生什么样的混乱。这是一个类似的线程,它更详细地解释了该问题 - C#: Nonzero-based arrays are not CLS-driven

  • 我对此投了反对票,因为这是一个危险的错误答案。Dot Net 框架支持非零基数组,以保持与旧 COM/DCOM 组件的兼容性。特别是 Excel.Range 对象的必要本地副本需要一个基于 1 的二维数组。可以使用 Array.CreateInstance() 文档将数组的尺寸设置为非零:https://msdn.microsoft.com/en-us/library/x836773a(v=vs.110).aspx (7认同)
  • 完全错误的说法。请参阅 Jeffrey L Whitledge 的回答。 (4认同)
  • 实际上,您可以在 C# 中创建基于 1 的数组,请参阅下面的最佳答案。 (2认同)