2010-10-12 2 views
3

У меня есть небольшая библиотека C# со статическим классом, которая содержит очень большой, но простой четырехмерный массив байтов, представляющий многомерную таблицу решений (всего около 90 Кбайт)."System.TypeLoadException: Внутреннее ограничение: слишком много полей." С большой структурой статических данных

Там есть еще одна структура данных, словарь, который помогает индексировать в первом измерении таблицы решений.

Эта таблица решений является статическим частным элементом данных, инициализированным статическими инициализаторами массива. Код создается в Visual Studio 2010 с помощью T4, из документов Excel.

Решения получены с помощью статического метода, который индексируется в многомерный массив.

Когда я запускаю простое тестовое приложение, используя эту библиотеку, он бомбит «System.TypeLoadException: Внутреннее ограничение: слишком много полей». Исключение при первом вызове метода статического решения.

Тема на Stackoverflow упоминает библиотеки со «слишком большим количеством символов». Возможно, я ошибаюсь, но в моей библиотеке действительно очень мало символов.

Что здесь происходит?

Код сниппета:

 private static byte[][][][] decisions = new byte[][][][] { 
    new byte[][][] { 
    new byte[][] { 
    new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6} 

    }, 
    new byte[][] { 
    new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}, 
    new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6} 

    }, 

... и так далее ...

ответ

4

новый байт [] {5,6,6}

Проблема здесь состоит в том, что инициализатор {5, 6, 6} создает статическое поле. Вы можете увидеть его с помощью Ildasm.exe. CLR налагает максимум, я считаю, 65535 полей в классе. Ваш автоматически сгенерированный код превышает его.

Вам нужно будет сделать это по-другому. Файл подскакивает.

+0

Я думаю, что кодирование данных в файл является лучшим вариантом. Если вы действительно хотите запретить пользователю изменять данные, вы можете вставить этот файл в качестве ресурса. –

+0

Я люблю Stackoverflow !!Мои цели - быстрый поиск и неясность (данные решения должны быть сложны для обратного проектирования). Файл ресурсов, вероятно, как сериализованный объект –

+0

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

0

Wow. Смотрится весело. Я не могу прокомментировать эту конкретную ошибку (хотя я ожидаю, что на самом деле слишком много промежуточных локалей), но во что-то замечательно похожее (механизм решения на основе кодека) Я заполнил данные через сериализацию (двоичный код в моем случае, но любой должен Работа). Это означало двухступенчатую загрузку (создание obj, загрузка из файла), но она работала очень хорошо.

В стороне: Моего конструктора было достаточно, чтобы отражатель взорвался в беспорядочной куче (очень конечная ошибка), поэтому я чувствую вашу боль.

0

Вы можете попытаться явно исправить код в статическом конструкторе и индексировать непосредственно в подматрицы, а не использовать синтаксис инициализатора массива. Это предотвратит создание статических полей и, вместо этого, закодирует все данные в массивный блок IL. Я не уверен, есть ли аналогичные ограничения на количество ИЛ, которое может идти в одном методе, но я уверен, что вы узнаете, измените ли вы T4 соответственно.

Это будет выглядеть так:

static MyClass() 
{ 
    decisions = new byte[N1][][][]; 
    decisions[0] = new byte[N2][][]; 
    .... 
    decisions[0][0][0][0] = 5; 
    decisions[0][0][0][1] = 6; 
    decisions[0][0][0][2] = 6; 
    ... 
} 
+0

Спасибо, Дэн. Я отмечаю ваш первый ответ как принятый ответ, потому что он определил корень моей проблемы! Я закончил тем, что упростил свой массив даже больше, чем вы предлагаете, до простого одномерного массива. Учитывая подход кода-ген, который я принял, и если предположить, что каждое измерение имеет известный размер в кодовом гене (что он и делает), решения эквивалентны, IMO. –

+0

Только что заметил ответ, который я обозначил, принадлежит Гансу. Извините Ханс и спасибо всем! –