10

I use this code to get a String array of headings used in a MS Word 2007 document (.docx):

dynamic arr = Document.GetCrossReferenceItems(WdReferenceType.wdRefTypeHeading);

Using the debugger, I see that arr is dynamically assigned a String array with titles of all my headings in the document (about 40 entries). So far so good.

Then, I want to access the strings, but no matter how I do it, I get the following exception:

InvalidCastException: 
           Unable to cast object of type 'System.String[*]' to type 'System.String[]'.

I have tried different ways of accessing the strings:

By index:

String arr_elem = arr[1];

By casting to an IEnumerable:

IEnumerable list = (IEnumerable)arr;

By using a simple foreach loop:

foreach (String str in arr)
{
   Console.WriteLine(str);
}

However, no matter what I try, I always end up with the same exception as shown above.

Can anyone explain what I am missing here / what I am doing wrong? And especially String[*] - what does it mean?

Lasse Christiansen
  • 10,205
  • 7
  • 50
  • 79
  • I have raised this with MS as a bug: https://connect.microsoft.com/VisualStudio/feedback/details/684538/dynamic-incorrectly-treats-1d-arrays-as-vectors – Marc Gravell Aug 17 '11 at 18:13

3 Answers3

8

string[] is a vector - a 1-d, 0-based array. string[*], however, is a regular array that just happens to have one dimension. Basically, you are going to have to handle it as Array, and either copy the data out, or use the Array API rather than the string[] API.

This is the same as the difference between typeof(string).MakeArrayType() (the vector) and typeof(string).MakeArrayType(1) (a 1-d non-vector).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Do you think it's a bug that the dynamic runtime is trying to access an array as if it were a vector? – Gabe Aug 16 '11 at 20:35
  • @Gabe - yes: https://connect.microsoft.com/VisualStudio/feedback/details/684538/dynamic-incorrectly-treats-1d-arrays-as-vectors – Marc Gravell Aug 17 '11 at 18:13
7

try

object arr_r = Document.GetCrossReferenceItems(WdReferenceType.wdRefTypeHeading);
Array arr = ((Array) (arr_r));

string myHeading = (string) arr.GetValue(1);
Yahia
  • 69,653
  • 9
  • 115
  • 144
5

The problem is that you're using dynamic in a situation where it apparently wasn't intended. When the dynamic runtime sees a 1D array, it assumes a vector, and tries to index into it or enumerate it as if it were a vector. This is one of those rare cases where you have a 1D array that is not a vector, so you have to handle it as an Array:

Array arr = (Array)(object)Document.
            GetCrossReferenceItems(WdReferenceType.wdRefTypeHeading);
// works
String arr_elem = arr.GetValue(1);
// now works
IEnumerable list = (IEnumerable)arr; 
// now works
foreach (String str in arr)
{
    Console.WriteLine(str);
}
Gabe
  • 84,912
  • 12
  • 139
  • 238
  • Thanks for your explanation :) Your first line throws me an InvalidCastException: Unable to cast object of type 'System.String[*]' to type 'System.String[]'. – Lasse Christiansen Aug 17 '11 at 06:39
  • @sw_lasse: Oops, you're right. I fixed it. My version worked in C# 3.0 but broke in 4.0 due to the apparent bug in the dynamic access of a nonstandard array. – Gabe Aug 17 '11 at 06:56