How to avoid "cctor () is too complex" error with Lists ?

Hello,
Background: I come from a decade+ of Flash & Actionscript experience. I have about 100+ hours into Unity and learning C# so far. I’ve gotten past many hurdles that have allowed me to make good progress on a 2D poker game.

I have converted a Poker hand evaluator from Actionscript 3 to C#, to the extent that the IDE is no longer reporting any errors, and so I’m now starting unit testing of some of the key parts of this evaluator. (Original AS3 is here: GitHub - houen/PokerFace: Actionscript 3 poker hand strength evaluation library and OO wrappers )

I’ve hit a wall fairly fast with some large (but not insanely large) data lists. In AS3 these were untyped Arrays:

flushes: 7937
perm7: 21
primes: 13
products: 4888
unique5: 7937
values: 4888

In C# I defined each one as a public static List typed for int or uint (depending on which one it is). Couple examples (truncated):

public static List<int> primes = new List<int> {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41};
    public static List<uint> flushes = new List<uint> {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 1599, 0, 0, 0, 0, 0, 0, 0, 1598, 0, 0, 0, 1597, 0, 1596,
        8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1595, 0, 0, 0,
        0, 0, 0, 0, 1594, 0, 0, 0, 1593, 0, 1592, 1591, 0, 0, 0, 0, 0, 0, ...

So far so good, but I get a very cryptic error when I try to access one of these Lists from my gamecontroller:

InvalidProgramException: Method CactusArrays:.cctor () is too complex.
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for CactusArrays
UnityEngine.Events.InvokableCall.Invoke (System.Object[ ] args)

(CactusArrays is the name of this class). I did many searches and some reading that lead me to believe that thousands-long data definitions of Lists should probably be moved to Start(), but my attempt to do that lead to different errors saying there was no object instance…

Anyways, I’m hitting a wall and have gone in circles a couple times. Does anyone have any advice? Should I be using a different kind of Array substitute, maybe List isn’t meant to be very long? Maybe I should be defining the length first??

I will note that in AS3 there are no issues, no slow-down so that leads me to believe this is not a memory limit issue. But who knows. Different engine, different language, different beast.

Please post the code you tried here that did not work.

Not really a solution to your problem, but a general tip: Unless your values hit the int32 limit of 2,147,483,647, you should refrain of using uint, or any unsigned types, for CLS-compliance reasons.

Further Reading Material

A few notes:

  1. I was able to paste in a huge amount (like 30 screens full of numbers, ended up being >30k items in the list) of values into the flushes array (copying your syntax here), and it compiled without issue. I could also output values from it in my script’s Awake with no issue.
  2. if you have an array that mostly consists of zeroes, you’re probably better off rethinking your algorithms.
  3. if your array isn’t going to change, you’d typically be better off using builtin array rather than lists (slightly better performance, esp when looping through them). I’m not aware of any size limits or anything for List<> though (plus, as mentioned, I can’t reproduce your problem even with thousands of items), so I can’t say if this would actually impact your problem at all.
2 Likes

@ Thanks for the tip. I changed all the Lists to use int and it made no difference. I’ll keep it in mind moving forward.

@StarManta Thank you for looking into this and assisting. I’ve attached two variations of this class.

  1. CactusArrays
    The first version has all data defined right in the beginning, where the Lists are defined. It compiles without error, but upon calling this class, the result is “.cctor () too complex” error.

To test, a function called by a button has this line:

int test = CactusArrays.primes[7];
  1. CactusArrays2
    This second version is what I tried when my hunch was that initialization of the data was the problem. I moved all List data populating into Start()

Testing is of course, the same, but with a 2 in the class name.

int test = CactusArrays2.primes[7];

The error I get here is
“NullReferenceException: Object reference not set to an instance of an object”

Since the class is not tied to a game object… OH, OH… (lightbulb!) Am I supposed to do something like:
Object myCactus = new CactusArrays() ???

3009395–224514–CactusArrays.cs (141 KB)
3009395–224515–CactusArrays2.cs (140 KB)

Continuing on with my lightbulb moment regarding version 2, I fixed up my use of the class as an object and guess what error I get now?

InvalidProgramException: Method CactusArrays2:.cctor () is too complex.
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for CactusArrays2

So, regardless if defined initially, or later in Start, same error.

Does this happen to be in a Monobehaviour or class that’s serialised via the inspector? You may be hitting the limits of Unity’s serialisation system.

Just a hunch, but worth looking into.

It’s not a Monobehaviour, it’s just a generic public class with some static Lists (sorry, I don’t know the proper term off the top of my head).

Coming back to this StarManta, you mention “builtin array”. What is this?? I have previously and now again searched for other arrays in the Unity manual and elsewhere and the closest thing I came across is ArrayList. But everywhere people say this is old, slow and not recommended. Everyone keeps recommending Generic Lists.

I’ve tested and tested some more… I’ve moved the data populating up to the main definition one by one and have narrowed down the culprit to the “products” List ! This is the one that triggers .cctor is too complex ! Now I just need to figure out WHY!

The suggestion is a plain vanilla array.

https://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

It’s hands down the best collection is you don’t need to resize it.

2 Likes

@Kiwasi YOU NAILED IT! I had no idea you could declare an array this way (I should have opened my C# beginners book instead of Googling).