« System.TypeLoadException: limitation interne: trop de champs. » Avec grande structure de données statique

StackOverflow https://stackoverflow.com/questions/3918785

  •  29-09-2019
  •  | 
  •  

Question

J'ai une petite bibliothèque C # avec une classe statique qui tient une très grande, mais simple, tableau d'octets à quatre dimensions représentant une table de décision multidimensionnelle (environ 90K octets au total).

Il y a une autre structure de données de la note là-bas, un dictionnaire qui aide index dans la première dimension de la table de décision.

Cette table de décision est un membre de données privées statique, initialisé par initialiseurs statiques de tableau. Le code est généré dans Visual Studio 2010 avec T4, à partir de documents Excel.

Les décisions sont obtenues par une méthode de statique qui indexe dans le tableau multidimensionnel.

Quand je lance une application de test simple en utilisant cette bibliothèque, il bombes avec un « System.TypeLoadException: limitation interne: trop de champs. » Exception, lors de la première invocation de la méthode de décision statique.

Le un sujet lié à distance sur Stackoverflow mentionne les bibliothèques avec « trop de symboles ». Je peux me tromper, mais ma bibliothèque semble avoir très peu de symboles en effet.

Qu'est-ce qui se passe ici?

Code Snippet:

        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}

    },

... et ainsi de suite ...

Était-ce utile?

La solution

  

nouvel octet [] {} 5,6,6

Le problème ici est que l'initialiseur {5, 6, 6} crée un champ statique. Vous pouvez le voir avec Ildasm.exe. Le CLR impose un maximum, je crois, 65535 champs dans une classe. Votre code généré automatiquement est le dépasser.

Vous allez devoir le faire différemment. Un fichier saute à l'esprit.

Autres conseils

Wow. Ça a l'air drôle. Je ne peux pas commenter sur cette erreur spécifique (bien que je pense qu'il est en fait trop de gens du pays intermédiaires), mais quelque chose de remarquablement similaire (moteur de décision basée codegen) Je peuplé les données via la sérialisation (binaires dans mon cas, mais tout devrait fonctionner). Cela signifiait une charge en deux étapes (créer obj, charge à partir du fichier) mais il fonctionnait très bien.

En aparté: Mon constructeur était assez pour faire réflecteur exploser dans un tas de désordre (erreur très terminal) donc je ressens votre douleur.

Vous pouvez essayer à émettre le code dans le constructeur statique explicitement et l'index directement dans les sous-réseaux plutôt que d'utiliser la syntaxe tableau initialiseur. Cela permettra d'éviter la création des champs statiques et encoder au lieu toutes la configuration de données dans un blob massif d'IL. Je ne sais pas s'il y a des limites similaires sur la quantité d'IL qui peut aller dans une seule méthode, mais je suis sûr que vous saurez si vous modifiez en conséquence le T4.

Il ressemblerait à ceci:

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;
    ...
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top