Как создать 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:
Я возьму Эрик Липперт за это, если он скажет "Нет очевидного способа сделать ненулевой массив на С#"
Ответы
Ответ 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, и если вы создадите массив и заселяете его локально, его можно заставить преуспеть в одном межпроцессном вызове, создавая огромное улучшение производительности.