[Mono.Android] J.L.Object casts w/ unsigned types are errors (#945)
Context: https://bugzilla.xamarin.com/show_bug.cgi?id=59193 Java does not include types to represent unsigned integers. This poses a problem when either porting code from Java to managed languages or when attempting to cast integer values between the Java and the managed land. The issue described in the above bug could be fixed by adding appropriate implicit and explicit operators to Java.Lang.Object in Xamarin.Android but that would allow for behavior which may have adverse effects without any external signs immediately visible to the developer. Consider a situation when a minimum signed 32-bit integer value returned by Java code is cast to the managed `uint` type - we end up with the same value but with different sign and no indication given that such a thing happened. We could up-cast the value to long but that changes the type of the result and is not advisable, especially with implicit conversions. Also, even if the value was up-cast to a type with a larger value range this would have to stop with the 64-bit integers since they can't be up-cast to any other primitive integer type. Any casts between signed and unsigned integer types should be a conscious and explicit action, thus the double cast `(ulong)(long)value` is considered the correct behavior. For those reasons we decided that the best action to to take is to actively prevent direct casts from/to a managed unsigned integer type to/from a signed Java integer type. This is implemented by way of adding a number of explicit and implicit conversion operators to XA's Java.Lang.Object implementation that are marked "obsolete" and being erroneous. This is done this way so that the code attempting to perform such conversions won't build because the compiler, seeing the attribute, will signal an error and abort the build.
This commit is contained in:
Родитель
9e0ee535b8
Коммит
7f8f50c80f
|
@ -484,6 +484,12 @@ namespace Java.Lang {
|
|||
return new Java.Lang.Boolean (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(Java.Lang.Byte)(sbyte) value`", error: true)]
|
||||
public static implicit operator Java.Lang.Object (byte value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static implicit operator Java.Lang.Object (sbyte value)
|
||||
{
|
||||
return new Java.Lang.Byte (value);
|
||||
|
@ -494,11 +500,23 @@ namespace Java.Lang {
|
|||
return new Java.Lang.Character (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(Java.Lang.Integer)(int) value`", error: true)]
|
||||
public static implicit operator Java.Lang.Object (uint value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static implicit operator Java.Lang.Object (int value)
|
||||
{
|
||||
return new Java.Lang.Integer (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(Java.Lang.Long)(long) value`", error: true)]
|
||||
public static implicit operator Java.Lang.Object (ulong value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static implicit operator Java.Lang.Object (long value)
|
||||
{
|
||||
return new Java.Lang.Long (value);
|
||||
|
@ -526,6 +544,12 @@ namespace Java.Lang {
|
|||
return Convert.ToBoolean (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(byte)(sbyte) value`", error: true)]
|
||||
public static explicit operator byte (Java.Lang.Object value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static explicit operator sbyte (Java.Lang.Object value)
|
||||
{
|
||||
return Convert.ToSByte (value);
|
||||
|
@ -536,11 +560,23 @@ namespace Java.Lang {
|
|||
return Convert.ToChar (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(uint)(int) value`", error: true)]
|
||||
public static explicit operator uint (Java.Lang.Object value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static explicit operator int (Java.Lang.Object value)
|
||||
{
|
||||
return Convert.ToInt32 (value);
|
||||
}
|
||||
|
||||
[Obsolete ("Use `(ulong)(long) value`", error: true)]
|
||||
public static explicit operator ulong (Java.Lang.Object value)
|
||||
{
|
||||
throw new InvalidOperationException ("Should not be reached");
|
||||
}
|
||||
|
||||
public static explicit operator long (Java.Lang.Object value)
|
||||
{
|
||||
return Convert.ToInt64 (value);
|
||||
|
|
Загрузка…
Ссылка в новой задаче