Как создать 1-мерный массив в C # с индексом, начинающимся с 1 - PullRequest
14 голосов
/ 20 апреля 2011

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

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[]'"

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

Обновление:

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

Ответы [ 3 ]

25 голосов
/ 20 апреля 2011

Вы можете создать ненулевой массив в 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));
        }

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

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

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

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

14 голосов
/ 04 ноября 2015

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

Я полностью согласен с тем, что они грязные, и их не следует использовать ни для чего, кроме устаревших вещей, но они необходимы для взаимодействия со старыми библиотеками 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'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);

    }

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

0 голосов
/ 20 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...