Patrick
(Patrick Lanz)
January 6, 2021, 4:10pm
1
Hello,
This has been tested with .NET 5.
In C#, there exists the following:
if (Value is String s)
{
// can use the s variable
}
In Oxygene, we can use (and it works):
with matching s := String (Value) do begin
// can use the s variable
end;
The problem is when trying to use a value type.
The following runs in C#:
if (Value is Int32 s)
{
// can use the s variable
}
The same construct generates an InvalidCastException
in Oxygene:
with matching s := Int32 (Value) do begin
// can use the s variable
end;
EDIT : corrected the Oxygene example, as per the third message.
mh
(marc hoffman)
January 8, 2021, 2:46pm
3
Hmm, I think this is as designed. since value types cant be null, I believe the ()
cast does the same as as
— raise an exception, since it’s can’t really return nil…
with s := nullable Int32(Value) do begin
might work?
Patrick
(Patrick Lanz)
January 8, 2021, 2:56pm
4
nullable Int32
works but it makes a conversion from Int32
to nullable Int32
.
I’ve made a little error in my first post: the equivalent in Oxygene
is:
with matching s := String (Value) do begin
// can use the s variable
end;
but it still generates an InvalidCastException
with values types.
What would be nice is if the compiler can generate the following.
Reference type
var s := String (value);
if assigned (s) then
...
Value type
if Value is Int32 then begin
var s := Int32 (Value;
...
end;
Patrick
(Patrick Lanz)
January 8, 2021, 3:00pm
5
A nice addition would be also for the case type
construct, as in C#:
case Value type of
var s : String : ; // can use local variable s as a String
var i : Int32 : ; // can use local variable i as an Int32
end;
mh
(marc hoffman)
January 8, 2021, 3:14pm
6
Well, you cant have your cake and eat it too :).
What is Int32(Value)
supposed to give you? if the result is supposed to be an integer, all it can to is fail (or return 0, with would be worse/really wrong)… If yu want to get back a potential null value, you have to use nullable.
Patrick
(Patrick Lanz)
January 8, 2021, 3:16pm
7
That’s why I corrected the example with matching
, so it should make sense then, no?
mh
(marc hoffman)
January 8, 2021, 3:19pm
8
well, those a re two entirely separate languages constructs
with matching NEW_VARIABLE := ANY_EXPRESSION do
will run the statement if NEW_VARIABLE
is non-null. the with
statement has no understanding of ANY_EXPRESSION, nor can (or should) int affect how that expression works
with matching s := Int32(Value) do begin
// can use the s variable
end;
is literally there exact same thing as
var s := Int32(Value);
if assigned(s) then begin
// can use the s variable
end;
and it cannot change what “Int32(Value)” does.
Patrick
(Patrick Lanz)
January 8, 2021, 3:22pm
9
So, if you prefer, provide a new syntax that let us check the type of a value and assign it to a variable of the right type…
As with matching
doesn’t work for nullable types, I thought it was a good solution for the syntax.
mh
(marc hoffman)
January 8, 2021, 3:29pm
10
Yes, we’d have to port over the mess that is C#'s patterns. Not sure if we want to do that to Oxygene, but I’ll bring it up for internal discussion.
Patrick
(Patrick Lanz)
January 8, 2021, 3:33pm
11
What is more readable?
if Value is Int32 then begin
var i := Int32 (Value);
...
end;
or
with matching i := Int32 (Value) do begin
end;
And for the case type
:
case Value type of
typeOf (Int32) : begin
var i := Int32 (Value);
...
end;
or
case Value type of
var i : Int32 : begin // or "i as Int32"
end;
end;
Patrick
(Patrick Lanz)
January 9, 2021, 6:23am
13
Perhaps with lambda expressions:
case Value type of
typeOf (Int32) : i -> ... // with begin...end for multi statements
end;