Bug 58393 - Bundle.putByteArray signature takes an unsigned byte array
Summary: Bundle.putByteArray signature takes an unsigned byte array
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: 7.3 (15.2)
Hardware: PC Windows
: --- normal
Target Milestone: abi-break-future
Assignee: Jonathan Pryor
Depends on:
Reported: 2017-07-25 17:55 UTC by Scott Mertz
Modified: 2017-09-21 19:29 UTC (History)
3 users (show)

See Also:
Is this bug a regression?: ---
Last known good build:


Description Scott Mertz 2017-07-25 17:55:32 UTC
Bundle.putByte correctly takes a signed byte (sbyte), but Bundle.putByteArray takes an unsigned byte array (byte[]).

Bundle b = new Bundle();
b.PutByte("key", -100);
b.PutByteArray("key", new sbyte[] { -100 }); // Fails to compile: Argument 2: cannot convert from 'sbyte[]' to 'byte[]'
Comment 1 Jon Douglas [MSFT] 2017-07-26 16:19:40 UTC
Here are the two definitions of these methods based on our API docs and Mono.Android.dll:

PutByte(String, SByte)

Inserts a byte value into the mapping of this Bundle, replacing any existing value for the given key.

PutByteArray(String, Byte[])

Inserts a byte array value into the mapping of this Bundle, replacing any existing value for the given key.


Given that Java's byte data type is an 8-bit signed two's complement integer, I would expect the PutByteArray method to also be a signed byte array in C#. Thus I am CONFIRMING this issue for consistency sake. There may be an internal reason that one of the Android engineers can answer further.

https://developer.android.com/reference/android/os/Bundle.html#putByte(java.lang.String, byte)

https://developer.android.com/reference/android/os/Bundle.html#putByteArray(java.lang.String, byte[])




Thank you for the report!
Comment 2 Jonathan Pryor 2017-09-21 19:29:37 UTC
This is not going to be fixed anytime soon.

There are 201 methods in API-26 which return a `byte[]`, and 364 methods which take a `byte[]` parameter (which may or may not overlap with the 201 which return a `byte[]`).

This may or may not sound like much, but there's another, *more* important, number: 51 of these methods are `non-virtual`, meaning 313 methods are `virtual`. That raises a very significant problem in our current binding system:

1. We want to maintain API stability. 32 of these methods are on interfaces. We *cannot* change those. (Changing interfaces is *bad*.)

2. Virtual methods can be overridden, and our binding infrastructure will do unknowable things if a class declares two virtual methods which bind the same Java method:

  partial class Intent {
    [Register ("putExtra", ...)]
    public virtual unsafe Intent PutExtra (string name, byte[] value);

    [Register ("putExtra", ...)]
    public virtual unsafe Intent PutExtra (string name, sbyte[] value);

That may look fine, but if a derived class overrides both of those methods, which should get invoked? They're the same Java method; There Can Be Only One™ override. Even if a class *doesn't* override both classes, the question remains: our current binding infrastructure can't handle this scenario.

In short, a global search-and-replace of `byte[]` with `sbyte[]` isn't going to happen. It has the potential to break too much. Selective overloads of existing methods with `sbyte[]` parameters *could* happen, but only if those methods are non-virtual (all 51 of them!).

A complete fix of this bug is nigh impossible without an ABI break. We have some ideas for a new API, but those all involve requiring C#8, so even if we pursue that idea, it won't see the light of day anytime soon.

Leaving this bug open if only to track the underlying idea.

Note You need to log in before you can comment on or make changes to this bug.