Подтвердить что ты не робот

Как создать 1-мерный массив в С# с индексом, начинающимся с 1

Для многомерных массивов Array.CreateInstance может использоваться для создания ненулевых массивов на основе индексов, но если вы попробуете это для 1-мерных массивов (векторов), как, например,:

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

это не удастся во время выполнения, когда сбрасывается из многомерного массива в одномерный массив

"Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'"

Теперь я мог бы просто создать нулевой массив и игнорировать первое значение или работать с смещениями и т.д., но могу ли я игнорировать некоторую синтаксическую магию С#, которая позволяет использовать векторы с нулевым основанием?

Update:

Я возьму Эрик Липперт за это, если он скажет "Нет очевидного способа сделать ненулевой массив на С#"

4b9b3361

Ответ 1

Все массивы в С# основаны на нулевом значении. Насколько я знаю, нет способа создать массив на основе 1. Представьте себе, какой был бы беспорядок, если бы это было возможно. Вот аналогичный поток, который объясняет проблему более подробно - С#: массивы с ненулевым базисом не совместимы с CLS

Ответ 2

Вы можете создать массив с ненулевым значением в С#, но его использование является отчасти неприятным. Это определенно не простая замена нормального (т.е. Одиночного размерного массива с нулевым основанием).

        // 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));
        }

Синтаксис GetValue/SetValue, который требуется для этого, является более уродливым, чем вычитание из векторного индекса при каждом возникновении.

Если тип значения хранится в массиве, он будет сохранен в последовательной позиции точно так же, как и в обычном массиве, но для получателя и сеттера потребуется бокс для значений (если только не существует какой-то магии компилятора, осознавая). И геттеру обычно требуется бросок (просто чтобы сделать его еще более уродливым).

    double myValue = (double)myArray.GetValue(index);

Также обратите внимание, что правильное сравнение для GetUpperBound составляет <=, в отличие от Length, которое сравнивается с <.

Ответ 3

Нет основанные на нулевом массиве массивы DO существуют в C, и существует способ создания массива на основе 1 (или любого другого).

Я полностью согласен с тем, что они беспорядочны, и они не должны использоваться ни для чего другого, кроме старого, но они ESSENTIAL взаимодействуют со старыми COM-библиотеками.

Наиболее распространенное место для работы с этим - это работа с объектом Microsoft.Office.Interop.Excel.Range в библиотеке Excel, которая по-прежнему использует старый интерфейс 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 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);

    }

В этом случае причина, по которой этот код необходим, - это вызов DCOM для excel - это межпроцессный вызов, и если вы будете получать доступ к ячейкам один раз, вы понесете огромные накладные расходы (либо извлечение или установка значений). Диапазон Excel - это 2-мерный массив на основе 1, и если вы создадите массив и заселяете его локально, его можно заставить преуспеть в одном межпроцессном вызове, создавая огромное улучшение производительности.