public class TestClass {
public static void test() {
// ok
#if ECHOES
Nullable<int> a = 5;
#elif COOPER
java.lang.Integer a = 5;
#elif NOUGAT
Foundation.NSInteger a = 5;
#endif
gint ga = 5; // (E62) Type mismatch, cannot assign "Integer"/"Int32" to "gint"
a = ga; // ok
doSth(a); // ok
doSth(ga); // COOPER: (E62) Type mismatch, cannot assign "gint" to "Integer"
// ECHOES/NOUGAT: (E486) Parameter 1 is "gint", should be "Int32", in call to static void TestClass.doSth(Int32 v)
}
public static void doSth(int v) {
}
}
#if ECHOES
public __mapped struct gint => Nullable<int> {
#elif COOPER
public __mapped class gint => java.lang.Integer {
#elif NOUGAT
public __mapped struct gint => Foundation.NSInteger {
#endif
}
Elements 8.3.92.1895
This can be reproduced on all platforms Android/.NET/iOS
This can be reproduced for other wrapped value types: Boolean, Double, etc.
public __mapped class gint => java.lang.Integer{
}// for Android
public __mapped struct gint => Foundation.NSInteger{
} // for iOS
public __mapped struct gint => Nullable<int>{
} // for .NET
and get the same compile errors…But the target classes themself can work under the same context, for example, the implicit conversion of java.lang.Integer and raw int is OK.
I think int? is only an alias name for a specified type on different platform, so I just try to use it to reduce duplicated code.
This issue is found because I try to make things like:
#if ECHOES
public __mapped struct gint => int {
}
#elif COOPER || NOUGAT
public __mapped class gint => int? {
}
#endif
So I can use gint to implement generic interface/delegate with a clean code:
public interface ITestInterface<T>{
T get();
}
public class TestClass : ITestInterface<gint>{
public gint get() => 5;
}
Otherwise, cross-platform code will be terrible:
public class TestClass : ITestInterface<int>{
#if ECHOES
public int get() => 5;
#else
public int? get() => 5;
#endif
}
Another example:
public class List<T> {
public delegate int Comparer<T>(T a, T b);
public void sort(Comparer<T> comparer) {
// ...
}
}
public static class ListComparer {
// Without gint
#if ECHOES
public static int intDescent(int a, int b) {
#else
public static int intDescent(int? a, int? b) {
#endif
return b - a;
}
// With gint
public static int intDescent(gint a, gint b) {
return b - a;
}
}
public class TestCode {
public void test() {
var list = new List<int>();
list.sort(ListComparer.intDescent);
}
}
Hrmm, if mapping to nullable is disabled, I have to change codes which works now:
public mapped class gint => int?{
}
to #if COOPER
public __mapped class gint => java.lang.Integer{ #elif NOUGAT
public __mapped class gint => Foundation.NSInteger{ #elif ECHOES
public __mapped struct gint => Nullable<int>{ #endif
}
its mapping to a nullable type that makes no sense. a nullable type is not an actual distinct type. the type is, say, int. a variable of type int? can be still points to an int, (or to null). there’s no such thing as a “nullable int” type the can live at runtime (platform specific implementation details aside). you can not allocate a “nullable int”. you cannot have an instance off a “nullable int”. you can have an int instance or not have an int instance.
I think int? is only an alias name for a specific type, which means for example: int? will become java.lang.Integer for Java when compile.
So the only reason I will use int? in C# is I want to use this alias name to replace duplicated codes, just like we use object to replace different specific object types (java.lang.Object, System.Object, NSObject etc.)
Correct me if I’m wrong.
Making a mapping type to int? is my attempt to solve a generic problem for raw types:
Still don’t see any benefit from simply disabling mapping to nullable types in RO C#…
If a nullable type (such as nullable raw types on all platforms as far as we know) is only an alias name of a specific real type, the mapping should be legal.
If a nullable type whose “nullable” is only a concept for compiler, it can be simply ignored in mapping because there’s no side-effect.
On the other side, the generic type problem for raw types in cross-platform code as I described exists, proving mapping types to nullable raw types are useful.
Actually this reported bug has nothing to do with mapping to nullable types. The cause is the mapping type mechanism can’t work well for some specific real types.
(Here refer to my another unresolved report months ago: Mapped class to Class can’t work on iOS)
Maybe it’s my fault to drag in things like int? in my bug report…
If mapping to nullable type is disabled in the next beta, I should change my report title and description by replacing int? with java.lang.Integer, NSInteger and Nullable<int>.
What do these three vars do? are z and z nullable? not nullable? is y double nullable? what?
var x: MyInt;
var y: nullable MyInt;
var z: not nullable MyInt;
sure it could be ignored. but that’s one imprecise and confusing, there’s all sort son stuff thats technically wrong that we could just “ignore”. but different than human languages, programming languages tent to want to be precise, and consider “wrong” stuff as errors.
right, which is why i logged a separate issue for the actual problem.
ok…I don’t get used to using “nullable” and “non-nullable” concepts much in my dev yet, since official C# and Java are not fond of these concepts stressed by Swift. (Official C# thinks only non-nullable value types can be attached with nullable modification)
Well, I will modify my origin bug report in order to meet new limitations.
Then on 8.3.92.1901, I can define the gint but it can’t work as a mapped type without explicitly defined gint<->int? operators, so it’s the bug 73822 I reported in this thread.
It seems be fixed on COOPER and ECHOES, but still need to define implicit operators to make it work on NOUGAT.
Here’s the test code:
public __mapped struct gint => Foundation.NSInteger {
// Uncomment below operators to eliminate compile errors
// public static implicit operator gint(int r) => r;
// public static implicit operator int(gint g) => g;
}
public class TestClass {
public TestClass() {
gint a = 5; // error: (E62) Type mismatch, cannot assign "Int32" to "gint"
int aa = a; // error: (E62) Type mismatch, cannot assign "gint" to "Int32"
doSth(a); // error: (E486) Parameter 1 is "gint", should be "Int32", in call to void TestClass.doSth(Int32 v)
}
public void doSth(int v) {
}
}
oh! but that’s not a bug. The big difference here is that you use NSInteger, which is an int64, if you use int32 it works. Otherwise you need conversion methods.