3

I use an interface to access an old application. From this application I have some "double array" which I can't access.The return type is declared as virtual dynamic. Whenever I access the array I got an exception.

On this question I found out that it may be because of the wrong indexed array. So I've tried the proposed solution but as I said I could not even access the array once without getting the exception.

Any idea on what the error could be?

Code with Hans approach:

var dataSetValues = dataSet.DoubleArray;
var result = ConvertDoubleArray(dataSetValues); // <<<<<< This is where I get an exception

public static double[] ConvertDoubleArray(Array arr)
{
    if (arr.Rank != 1) 
        throw new ArgumentException();

    var retval = new double[arr.GetLength(0)];
    for (int ix = arr.GetLowerBound(0); ix <= arr.GetUpperBound(0); ++ix)
        retval[ix - arr.GetLowerBound(0)] = (double) arr.GetValue(ix);
    return retval;
}

Interface declaration of DoubleArray:

public virtual dynamic DoubleArray { get; set; }

Runtime type information: enter image description here

Exception:

System.InvalidCastException: Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'. at CallSite.Target(Closure , CallSite , VirtualEnvironmentManager , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) at FormulaTestExecutor.Common.VirtualEnvironmentManager.CreateVirtualStructure(Formula formula) in D:\Develop\TFS\Main\tools\FormulaMTest\FormulaTestExecutor\FormulaTestExecutor\Common\VirtualEnvironmentManager.cs:line 55

Stacktrace of Exception:

FormulaTestExecutor.exe!FormulaTestExecutor.Common.VirtualEnvironmentManager.CreateVirtualStructure(FormulaTestExecutor.Model.Formula formula = {FormulaTestExecutor.Model.Formula}) Line 55 C# Symbols loaded. FormulaTestExecutor.exe!FormulaTestExecutor.Program.Main(string[] args = {string[0]}) Line 18 C# Symbols loaded.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
Hendrik
  • 93
  • 9
  • You did not understand the posted answer correctly, you can **not** declare the array as Double[]. It must be `Array dataSetValues = dataSet.DoubleArray;`. Easy peasy. – Hans Passant Aug 24 '17 at 17:19
  • Array dataSetValues = dataSet.DoubleArray; does not change anything. – Hendrik Aug 24 '17 at 17:20
  • And yes I know the type from how it is written in the interface. – Hendrik Aug 24 '17 at 17:22
  • Well, of course it did, the code in your snippet is most definitely wrong. If you *want* a double[] then you still have to convert it with the proposed solution. Or only ever use the members of the Array class, whatever floats your boat. If the interface has declared the return type as double[] then you have a bigger problem, that is not clear from the question. Editing an interop assembly is possible by using ildasm.exe and ilasm.exe. – Hans Passant Aug 24 '17 at 17:22
  • So did you try `var result = ConvertDoubleArray(dataSet.DoubleArray);`? What error did you get and on what line? – Vikhram Aug 24 '17 at 17:25
  • Yes, I want a double[] but if I try it with the proposed solution I get the exception already at the assignment of the array. – Hendrik Aug 24 '17 at 17:26
  • I've tried it, but I already get the exception when I call the method. – Hendrik Aug 24 '17 at 17:31
  • The ConvertDoubleArray method. The code of this method will not be executed. – Hendrik Aug 24 '17 at 17:36
  • The only information I get is following: dataSetVales {double[1...1]} and also an question mark and an stop sign. – Hendrik Aug 24 '17 at 17:37
  • now this is so not plausible. the source location of the exception is not in line with the type of exception. if it throws on the very *call* to `ConvertDoubleArray` then it cannot be a failing cast from `double[*]` to `double[]`. please update us on the exact wording of the exception, make a try..catch around and give us ex.ToString() – Cee McSharpface Aug 24 '17 at 18:19
  • Do you have the code that creates the DoubleArray? And please post a decent english exception... – Simon Mourier Aug 24 '17 at 22:05
  • @dlatikay could you explain what you mean with: "the source location of the exception is not in line with the type of exception." because clicking on the exception at the stack trace points me exactly to the line of the ConvertDoubleArray(pdataSetValues) - method – Hendrik Aug 25 '17 at 06:53
  • @SimonMourier I don't have the code which creates the doubleArray. But in the old Application it seems to work without any problems because I can access these array in the GUI of this application. – Hendrik Aug 25 '17 at 06:55
  • 1
    What I mean is that I don't see how the runtime would throw an `InvalidCastException` with "Double[*]' to type 'System.Double[]", when the target type of the first and only argument to the called function is `Array`. Are you sure the code you run is the code you compiled? I would set a breakpoint on where `dataSetValues` is first assigned, and then step through with F11 to prove. – Cee McSharpface Aug 25 '17 at 07:49
  • Can you actually step into ConvertDoubleArray maybe this is a resolution error? – user6144226 Aug 25 '17 at 08:23

2 Answers2

3

You must do this:

var dataSetValues = dataSet.DoubleArray; // dataSetValues is dynamic
var result = ConvertDoubleArray((Array)(object)dataSetValues);

The reason is the 'dynamic' type of the DoubleArray (that was probably automatically defined in the interface when you added the COM reference). It's a super smart thing that tries to do the conversion from System.Double[*] to System.Double[] by itself, but it's not smart enough to do this (it can't read StackOverflow answers... yet)

So, you'll have to ask it to just pass the object 'as is', to be able to pass it directly to the CLR low-level cast, which can do System.Double[*] to Array w/o crashing. Once you have the Array, you can re-use the ConvertDoubleArray utility.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
0

Actually I find a solution on: Unable to cast object of type 'System.Single[*]' to type 'System.Single[]'

If I want to cast the safe array, I first need to cast it to an .NET object before I can cast it to an array.

var dataSetValues = (Array)(object)dataSetDoubleArray;
Hendrik
  • 93
  • 9