3

I have got a similar problem like Cheva had in his Question:

How to cast System.Object[*] to System.Object[]

I use an external library (Reuters EIKON API) via the COM interop functionality.

After submitting a request, the object gets updated and its data member gets updated. The Object catalogue shows this for the Data member:

public virtual dynamic Data { get; }

In the debug mode, I can see, that after submitting the request, DataStatus changes to dataset_full and the Data member is actually filled.

The data member is shown as {object[1..31]} and I can see from the debug dropdown menu, that there a actually strings in this collection.

My problem is that I can't access this object. I can cast it to object[] or string[] or anything. I can't even find out the type of it.

It always says System.Object[*] can not be cast to System.Object[]

if I try to find out the type by using .Type(), I get "System.Reflection.TargetInvocationException". I even cannot access the Length of it, this also gives me the error

System.InvalidCastException -> Object of Type "System.Object[*]" cannot be cast to type "System.Object[]"

Has anyone seen a similar error?

Community
  • 1
  • 1
user7815
  • 31
  • 2
  • Can you include your code you used for casting so we can see what you tried? – Scott Chamberlain Apr 29 '14 at 14:11
  • are you trying to cast a dynamic to an object[]? – Delta Apr 29 '14 at 14:21
  • 2
    It is a non-conformant array with a lower-bound that is not 0. Not uncommon in COM interop, starting at 1 is fairly typical. You can only cast to (Array). And use its GetLowerBound() method to know where to start indexing, GetUpperBound() to know where to stop, GetValue() to read an element. – Hans Passant Apr 29 '14 at 15:09
  • possible duplicate of [What does System.Double\[\*\] mean](http://stackoverflow.com/questions/23125903/what-does-system-double-mean) – Hans Passant Apr 29 '14 at 15:14
  • I'm facing the exact same problem here working VSTO. Excel.Filter.Criteria1 is dynamic, filter returns an "object[]" but behaves exactly as you've stated.. can't loop, no methods, properties, fields, members, nothing. Once dynamic has it, it can't be stored on another dynamic object. Use your 1 shot wisely! – Leo Gurdian Oct 26 '17 at 00:32
  • @LeoGurdian Your comments here and to my answer made me look into this again, and I found out I wanted to provide more information on the particular cocktail of using `dynamic` together with an actual type of `System.Object[*]`. So check out my expanded answer. – Jeppe Stig Nielsen Oct 26 '17 at 16:06

1 Answers1

4

System.Object[*] is a System.Array which is one-dimensional but not indexed starting from 0. It is not well supported in C#, because C# uses 0-based indexing.

A System.Object[*] is not an object[], so you can't cast to that type.

You can use:

var dataAsArray = (Array)Data;

or

var dataAsNonGenericIList = (IList)Data;

Then you can foreach through it.

Or you can access individual entries by index, like this:

object first = dataAsArray.GetValue(1);

respectively:

object first = dataAsNonGenericIList[1];

You will need to work out the upper and lower bounds (dataAsArray.GetLowerBound(0), dataAsArray.GetUpperBound(0)), but it seems that the lower bound is 1 in your case.

You can cast to string in the usual ways, (string)first if you expect it to be a string every time, or something like first as string (then check for null) if you want to support other objects.


If instead you want to copy the "weird" array to a 0-indexed array, see the linked thread without the numeral II in the title. Indexes will change, of course. For example object[] newArray = new object[dataAsArray.Length]; dataAsArray.CopyTo(newArray, 0);


Much later edit:

In addition to what I wrote above, there is a bug in the run-time binder used with C# dynamic functionality when the actual type is System.Object[*]. This could also be inferred from the question above. As an example (the array I create has rank one, the length of the sole dimension is 31, and the lower bound in that dimension is 1 (i.e. not zero-indexed)):

dynamic Data = Array.CreateInstance(typeof(object), new[] { 31, }, new[] { 1, });
dynamic t = Data.GetType(); // throws!
dynamic s = Data.ToString(); // throws!

In either case an InvalidCastException is thrown:

Unable to cast object of type 'System.Object[*]' to type 'System.Object[]'.

This is a bug, I would say. The members exist, and I did not ask to cast to that type, I asked for late-binding to members that exist.

The very same bug occurs at run-time when I cast directly from dynamic to Array or IList, as I did above in the original answer.

You can work around this bug in the following way:

var dataAsArray = (Array)(object)Data;

and:

var dataAsNonGenericIList = (IList)(object)Data;

Casting to object with late binding (i.e. from dynamic) does not appear to be affected by the bug. The the next cast, from object to Array (or to IList), is a normal down-cast with no dynamic magic, and that works of course.

With this, my answer has become useful (years later).

I am just realizing that an answer by RoadBump in a linked thread also gives this information, so go up-vote that answer.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • very well put, weird arrays. Thanks for shedding light but the thing is they contain no methods, members, fields, nothing just a list of "strings" as in my case as well. you can't even loop thru so unfortunately, your suggestions won't work. : ( – Leo Gurdian Oct 26 '17 at 00:10