Page 1 of 2
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:04 pm
by Karl-Heinz
Code: Select all
FUNCTION DoConsole2() AS VOID
LOCAL fTotal AS double
VAR aDouble := <OBJECT>{0.00,276.45,276.45}
Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble)
fTotal += (double) aDouble [ 3 ]
aDouble [ 1 ] := -1223.56
aDouble [ 2 ] := 7869
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]
Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble)
fTotal += (double) aDouble [ 3 ]
// 12 + 12 == 24
Console.WriteLine(space ( 24 ) + repl ( "-" , 20 ) )
// 12 + 12 + 20 == 44
Console.WriteLine("{0,44:###,###,##0.00}" , fTotal )
RETURN
find the (runtime) problem
regards
Karl-Heinz
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:17 pm
by wriedmann
Hi Karl-Heinz,
I had similar problems with conversions....
It is very bad that .NET does not handles this and that you have to specify
Code: Select all
aDouble [ 1 ] := -1223.56d
aDouble [ 2 ] := 7869d
Wolfgang
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:23 pm
by wriedmann
Hi Karl-Heinz,
an addition: this works also:
Code: Select all
aDouble [ 1 ] := ( double ) -1223.56
aDouble [ 2 ] := ( double ) 7869
In our VO understanding a numeric is a numeric and there is no runtime error when they are converted for and back.
It is really a pity that a numeric calculation between an int32 and a double fails at runtime!
Wolfgang
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:28 pm
by Chris
Guys,
.Net actually does handle it well, but we must be careful with what we are doing. The code (simplified to make it easier to follow):
Code: Select all
aDouble [ 3 ] := (double) aDouble [ 2 ]
Does a type cast from object to double, so we tell the compiler that we know that aDouble [ 2 ] holds a double, which apparently in this case is not true. What we really should be doing, is to use a conversion, not a cast, as in:
Code: Select all
aDouble [ 3 ] := Convert.ToDouble( aDouble [ 2 ] )
This will always work correctly, provided that the type of aDouble [ 2 ] can be converted to a double.
Of course he "Convert" method is slower, but it is safer to use in such code.
Chris
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:33 pm
by Chris
Hi Wolfgang,
wriedmann wrote:Hi Karl-Heinz,
an addition: this works also:
Code: Select all
aDouble [ 1 ] := ( double ) -1223.56
aDouble [ 2 ] := ( double ) 7869
In our VO understanding a numeric is a numeric and there is no runtime error when they are converted for and back.
It is really a pity that a numeric calculation between an int32 and a double fails at runtime!
Wolfgang
To be precise, it is not the calculation that fails, but the cast, which is indeed incorrect. You can do calculations between Int32 and Double just fine:
Code: Select all
LOCAL r AS REAL8
LOCAL n AS INT
r := n + r
as long as the target var type is "larger" (or same) than the operands.
But when you are doing calculations between objects that the runtime knows nothing about at compile time (calculation between System.Object types), then you need to convert them to the data type you want first.
Chris
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:35 pm
by Jamal
Not sure this is a .NET thing, but more of a language specific.
I used C# and VB.NET.
C# is very strict on casting, however, VB.NET handles double correctly.
Jamal
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 4:45 pm
by wriedmann
Hi Chris,
thank you very much for your explanations!
Theoretically also the cast from an int32 to a double should work....
Wolfgang
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 5:26 pm
by Chris
Hi Wolfgang,
wriedmann wrote:Hi Chris,
thank you very much for your explanations!
Theoretically also the cast from an int32 to a double should work....
Wolfgang
They are different data types, with different internal representation, and just because they are both numeric types, does not mean they can be cast one to another (of course
conversion is a different thing). It's like expecting to be allowed to do (System.Collections.SortedList)oMyDisctionary, because both SortedList and Dictionary are both collection types.
Try doing the equivalent of casting in VO:
Code: Select all
LOCAL n AS INT
LOCAL r AS REAL8
r := 1.2
n := INT(_CAST,r)
? n
this will not throw an exception/error in VO, but the result will not make sense either.
Note that in this particular case, in .Net such a (memory mapped) cast is not allowed, so if you compile this with X# (or vulcan), the compiler will actually create code that makes a conversion! It does that, because it knows at compile time exactly the data types involved (INT and REAL8) and can safely convert from one to another, while it cannot do that for vars declared as Object.
Edit: So, to summarize, my suggestion is when every time when dealing with objects that are non known at compile time, always use the Convert methods to be safe. Unless you want to use USAULs of course, which take care of this at runtime!
Chris
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 5:35 pm
by Karl-Heinz
Guys,
c# throws the same runtime error. The "problem" is that an array of "simple" Objects must be used to feed the Console.WriteLine(), instead of the possibility to use an typed array of e.g. doubles. The lesson learned in conjunction with "simple" Objects: Don´t trust your human senses, especially if you have VO roots
// something like this gives no such problems.
VAR fDouble := <DOUBLE>{2.50, 3 , 12.45 }
fDouble [ 1 ] := 1234
fDouble [ 2 ] := -12
fDouble [ 3 ] := fDOuble [ 1 ] + fDouble [ 2 ]
? fDouble [ 1 ]
? fDOuble [ 2 ]
? fDouble [ 3 ]
regards
Karl-Heinz
.net is a extremly dangerous thing ;-)
Posted: Wed Aug 29, 2018 5:46 pm
by Karl-Heinz
Hi Chris,
Chris wrote:
Edit: So, to summarize, my suggestion is when every time when dealing with objects that are non known at compile time, always use the Convert methods to be safe. Unless you want to use USAULs of course, which take care of this at runtime!
Chris
So this isn´t save enough ?
aDouble [ 1 ] := (double) -1223.56
aDouble [ 2 ] := (double) 7869
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]
regards
Karl-Heinz