简体   繁体   中英

C# Cast works only in debugger

I'm developing a mobile application which among other things, it receives data from medical devices via Bluetooth. To this end, I'm using an Android SDK in JAR via binding to my Xamarin project. Here's the class that holds the returned data from the decompiled JAR:

package com.contec.jar.contec08a;
import java.util.ArrayList;

    public class DeviceData
    {
      public ArrayList<byte[]> mData_blood = new ArrayList();
      public ArrayList<byte[]> mData_oxygen = new ArrayList();
      public ArrayList<byte[]> mData_normal_blood = new ArrayList();
    }

What is of interest is the mData_blood. Each element of the array list corresponds to a patient. Each byte array is the medical data for each patient. The Xamarin framework makes some changes, ie the name of the property becomes MDataBlood.

Problem : when I receive the above class and property, the casting fails BUT NOT in the debugger. Here's what I mean: the 'as' operator that implement the cast fails (returns null) but in the debugger the very same expression correctly shows the data. What's more, the 'is' operator returns false in runtime (the canDo variable is false) but true in the debugger. I've tried all methods of casting I'm familiar with, even using –but not mixing – Android objects. The highlighted line which casts the IList to List produces a nice exception. I'm at a total loss. Any suggestions would be greatly appreciated.

Here's the screenshot from the debugger which illustrates all the above:

调试器会话屏幕截图。

Edit1: The MDataBlood[0] evaluates as generic Java object. When reviewing its properties, its isArray is set to true. By checking the decompiled source of the SDK, I determined that is indeed byte array.

In Xamarin, there are some castings that might fail when the objects come from java types. In that cases you should use JavaCast<TResult> instead of a regular casting.

Try this, instead of your current approach:

// Since MDataBlood is exposed as an IList property of MDeviceData,
// we first need to cast it to IJavaObject
var dataBloodRaw = (IJavaObject)dm.MDeviceData.MDataBlood;

// Then we have access to its JavaCast method
var dataBlood = dataBloodRaw.JavaCast<JavaList<byte[]>>();

JavaList<T> extends Java.Lang.Object , so it can be used as the TResult parameter for JavaCast<TResult> . Also, it implements IList , so you should be able to loop through it.

Anyway, if you need a List<byte[]> you can use the casted JavaList for creating it:

var dataBloodList = dataBlood.ToList();

Or, alternatively

var dataBloodList = new List<byte[]>(dataBlood);

Yet another thing you could just try is to Java-cast dataBloodRaw to a JavaList<object> and then loop through its objects, trying to cast each one of them as a byte[] .

Plan B

If none of the above works, I suggest you to take a look at this answer where it is suggested to disable linking for Release , which can be done in your project properties:

在此处输入图片说明

Keep in mind that a side effect of this last option will be the impact on the final size of your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM