Ответ 1
В этой статье объясняется это: http://www.panopticoncentral.net/2004/03/17/non-zero-lower-bounded-arrays-the-other-side-of-the-coin/
Несмотря на то, что, возможно, дело в том, что нужно делать, мне нужно создать массив в .Net с нижней границей > 0. Это сначала кажется возможным, используя:
Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Производит требуемые результаты (массив объектов с нижней границей, установленными в 9). Однако созданный экземпляр массива больше не может передаваться другим методам, ожидающим Object[]
, давая мне ошибку, говорящую, что:
System.Object[*]
нельзя вставить в System.Object[]
. Каково это различие в типах массивов и как я могу это преодолеть?
Изменить: test code =
Object x = Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Object[] y = (Object[])x;
Сбой: "Невозможно передать объект типа" System.Object [*] "для ввода" System.Object [] ".
Я также хотел бы отметить, что этот подход DOES работает при использовании нескольких измерений:
Object x = Array.CreateInstance(typeof(Object), new int[] {2,2}, new int[] {9,9});
Object[,] y = (Object[,])x;
Что отлично работает.
В этой статье объясняется это: http://www.panopticoncentral.net/2004/03/17/non-zero-lower-bounded-arrays-the-other-side-of-the-coin/
Причина, по которой вы не можете отбрасывать друг от друга, это то, что это зло.
Предположим, вы создаете массив объекта [5..9] и передаете его функции F в качестве объекта [].
Как функция будет знать, что это 5..9? F ожидает общий массив, но он получает ограниченный. Вы могли бы сказать, что это возможно для него, но это все еще неожиданно, и люди не хотят делать всевозможные пограничные проверки каждый раз, когда хотят использовать простой массив.
Массив является самой простой структурой в программировании, что делает ее слишком сложной, что делает ее непригодной. Вероятно, вам нужна другая структура.
То, что вы делаете, - это класс, который представляет собой ограниченную коллекцию, которая имитирует поведение, которое вы хотите. Таким образом, все пользователи этого класса будут знать, чего ожидать.
class ConstrainedArray<T> : IEnumerable<T> where T : new()
{
public ConstrainedArray(int min, int max)
{
array = new T[max - min];
}
public T this [int index]
{
get { return array[index - Min]; }
set { array[index - Min] = value; }
}
public int Min {get; private set;}
public int Max {get; private set;}
T[] array;
public IEnumerator<T> GetEnumerator()
{
return array.GetEnumarator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return array.GetEnumarator();
}
}
Я не уверен, почему это невозможно передать как Object [], но будет непросто, если вы просто создадите настоящий класс, чтобы обернуть массив и обработать свою "странную логику" там?
Вы получили бы преимущества использования реального ссылочного объекта, если бы вы могли добавить "интеллект" в свой класс.
Изменить: Как вы производите свой массив, можете ли вы разместить еще какой-нибудь код? Спасибо.
Просто сохраните нижнюю границу в целочисленном смещении const и вычтите это значение из того, что ваш источник возвращает как индекс.
Также: это старая функция VB6. Я думаю, что для поддержки этого может быть атрибут.
Знай это старый вопрос, но чтобы полностью его объяснить.
Если тип (в данном случае одномерный массив с нижней границей> 0) не может быть создан типизированным кодом, тогда просто отраженный экземпляр типа не может быть использован типизированным кодом.
То, что вы заметили, уже есть в документации:
Обратите внимание, что с точки зрения времени выполнения, MyArray []! = MyArray [*], но для многомерных массивов эти два обозначения эквивалентны. Это is, Type.GetType("MyArray [,]") == Type.GetType("MyArray [*, *]") оценивается как истина.
В c #/vb/... вы можете сохранить этот отраженный массив в объекте, передать его как объект и использовать только отражение для доступа к его элементам.
-
Теперь вы спрашиваете "почему вообще существует LowerBound?", Ну, COM-объект - это не .NET, его можно было бы написать в старом VB6, у которого фактически был объект массива, для которого LowerBound был установлен в 1 (или что-нибудь в VB6 имело такую свободу или проклятие, зависит от кого ты спрашиваешь). Чтобы получить доступ к первому элементу такого объекта, вам на самом деле нужно использовать 'comObject (1)' вместо 'comObject (0)'. Поэтому причина для проверки нижней границы заключается в том, что когда вы выполняете перечисление такого объекта, чтобы знать, где начать перечисление, так как функции элемента в COM-объекте ожидают, что первый элемент будет иметь значение LowerBound, а не Zero (0), разумно было поддерживать та же логика в таких случаях. Представьте, что ваше значение элемента get для первого элемента равно 0, и используйте некоторый объект Com для передачи такого экземпляра элемента со значением индекса 1 или даже со значением индекса 2001 в метод, код будет очень запутанным.
Проще говоря: это в основном только для устаревшей поддержки!