Вопрос:

.Net массивы с нижней границей> 0

.net arrays

4428 просмотра

5 ответа

1184 Репутация автора

Хотя, возможно, это странная вещь, которую нужно сделать, мне нужно создать массив в .Net с нижней границей> 0. Сначала это кажется возможным, используя:

Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});

Производит желаемые результаты (массив объектов с нижней границей, установленной на 9). Однако созданный экземпляр массива больше не может быть передан другим методам, ожидающим, Object[]что я получаю сообщение об ошибке, в котором говорится:

System.Object[*]не может быть брошен в System.Object[]. В чем разница между типами массивов и как я могу это преодолеть?

Изменить: тестовый код =

Object x = Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Object[] y = (Object[])x;

Который завершается неудачно с: "Невозможно привести объект типа 'System.Object [*]' к типу" System.Object [] '. "

Я хотел бы также отметить , что этот подход ДЕЙСТВИТЕЛЬНО работает при использовании нескольких измерений:

Object x = Array.CreateInstance(typeof(Object), new int[] {2,2}, new int[] {9,9});
Object[,] y = (Object[,])x;

Который работает отлично.

Автор: DAC Источник Размещён: 11.09.2008 12:44

Ответы (5)


1 плюс

17259 Репутация автора

Я не уверен, почему это нельзя передать как Object [], но было бы нелегко, если бы вы просто создали реальный класс, чтобы обернуть массив и обработать вашу «странную логику» там?

Вы получили бы преимущества от использования реального эталонного объекта, если бы вы могли добавить «интеллект» в ваш класс.

Изменить: Как вы кастуете свой массив, не могли бы вы опубликовать еще немного кода? Благодарю.

Автор: Martin Marconcini Размещён: 11.09.2008 12:48

2 плюса

16967 Репутация автора

Решение

Эта статья объясняет это: http://www.panopticoncentral.net/2004/03/17/non-zero-lower-bounded-arrays-the-other-side-of-the-coin/

Автор: ibz Размещён: 11.09.2008 12:52

3 плюса

22116 Репутация автора

Причина, по которой вы не можете разыгрывать одно на другое, заключается в том, что это зло.

Допустим, вы создали массив объекта [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();
    }

}
Автор: Coincoin Размещён: 11.09.2008 01:09

1 плюс

319018 Репутация автора

Просто сохраните нижнюю границу в целочисленном смещении const и вычтите это значение из того, что ваш источник возвращает в качестве индекса.

Также: это старая особенность VB6. Я думаю, что мог бы быть атрибут, чтобы помочь поддержать это.

Автор: Joel Coehoorn Размещён: 11.09.2008 01:32

0 плюса

435 Репутация автора

Знайте, что это старый вопрос, но чтобы полностью объяснить это.

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

То, что вы заметили, уже есть в документации:

https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/specifying-fully-qualified-type-names

Обратите внимание, что с точки зрения времени выполнения MyArray []! = MyArray [*], но для многомерных массивов эти две записи эквивалентны. То есть Type.GetType ("MyArray [,]") == Type.GetType ("MyArray [*, *]") оценивается как true.

В c # / vb / ... вы можете хранить этот отраженный массив в объекте, передавать как объект и использовать только отражение для доступа к его элементам.

-

Теперь вы спрашиваете «почему вообще существует LowerBound?», Ну, COM-объект - это не .NET, его можно было бы написать в старом VB6, у которого фактически был объект массива, для которого LowerBound был установлен в 1 (или что-нибудь в VB6 имело такую ​​свободу или проклятие, зависит от кого ты спрашиваешь). Чтобы получить доступ к первому элементу такого объекта, вам на самом деле нужно использовать 'comObject (1)' вместо 'comObject (0)'. Поэтому причина для проверки нижней границы заключается в том, что когда вы выполняете перечисление такого объекта, чтобы знать, с чего начать перечисление, поскольку функции элемента в COM-объекте ожидают, что первый элемент будет иметь значение LowerBound, а не Zero (0), разумно было поддержать та же логика в таких случаях. Представьте, что ваше значение элемента get для первого элемента равно 0, и используйте некоторый объект Com для передачи такого экземпляра элемента со значением индекса 1 или даже со значением индекса 2001 в метод,

Проще говоря: это в основном только для устаревшей поддержки!

Автор: SoLaR Размещён: 14.08.2019 08:11
Вопросы из категории :
32x32