Mike Christensen
Mike Christensen

Reputation: 91598

Converting a List<> to an Array - I get "Attempted to access an element as a type incompatible with the array."

I'm trying to walk through a bunch of items, each item has an array of List<> objects that I want to convert to an array of arrays.. Here's the code to do that:

foreach (IngredientNode i in _snapshot._ingredientMap.Values)
{
   for (int c = 0; c < NUM_TAGS; c++)
   {
      if (i.RecipesByTag[c] == null) continue;
      i.RecipesByTag[c] = i.RecipesByTag[c].ToArray<RecipeNode>();
   } <--- EXCEPTION
}

RecipesByTag has a static type of IEnumerable<RecipeNode>[]. However, its dynamic type is List<RecipeNode>[]. I want to go through each one of those and convert the dynamic type of RecopeNode[]. Under the debugger, this works and i.RecipesByTag gets converted. However, the last curly brace then throws the exception:

Attempted to access an element as a type incompatible with the array.

I have a feeling there's some sort of stack corruption going on. Can someone explain what's happening at a technical level here? Thanks!

Upvotes: 4

Views: 10724

Answers (2)

John Leidegren
John Leidegren

Reputation: 60987

You shouldn't have to specify the type argument for the ToArray method, it should be inferred from it's usage, if you are using strongly typed collections. This is a generic type casting problem. You are trying to put elements in an array of some incompatible type.

Your problem should boil to this (these arrays are covariant):

object[] obj = new string[1];
obj[0] = 5; // compiles fine, yields runtime error

Now, the same thing, with different types (these arrays are also covariant):

IEnumerable<int>[] x = new List<int>[1];
x[0] = new int[1]; // compiles fine, yields runtime error

It should be obvious why the type system doesn't like this. Basically, you look at it as if it was an array of IEnumerable<int> but it's actually an array of List<int>. You can not put an unrelated type array of int, into that array.

I believe Eric Lippert explains this very well on his blog.

Upvotes: 6

Mike Christensen
Mike Christensen

Reputation: 91598

Okay I think I figured out what's going on.. I have an array of Enumerables. At first, this was an array of pointers to list objects. I instead made this an array of other arrays, in other words I converted my array into a multidimentional array. Since a multidimentional array is consecutive in memory (as opposed to an array of pointers to other arrays), doing this completely corrupted the array in memory. At least that's my theory.

What I did is completely recreate i.RecipesByTag from scratch. Something like this:

List<RecipeNode[]> temp = new List<RecipeNode[]>();

for (int c = 0; c < NUM_TAGS; c++)
{
   RecipeNode[] nodes = (i.RecipesByTag[c] == null) ? null : i.RecipesByTag[c].ToArray<RecipeNode>();
   temp.Add(nodes);
}

i.RecipesByTag = temp.ToArray();

This works perfectly.

Upvotes: 1

Related Questions