.net is a extremly dangerous thing ;-)

This forum is meant for anything you would like to share with other visitors
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

.net is a extremly dangerous thing ;-)

Post 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
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

.net is a extremly dangerous thing ;-)

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

.net is a extremly dangerous thing ;-)

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

.net is a extremly dangerous thing ;-)

Post 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
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

.net is a extremly dangerous thing ;-)

Post 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
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Jamal
Posts: 315
Joined: Mon Jul 03, 2017 7:02 pm

.net is a extremly dangerous thing ;-)

Post 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
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

.net is a extremly dangerous thing ;-)

Post by wriedmann »

Hi Chris,

thank you very much for your explanations!

Theoretically also the cast from an int32 to a double should work....

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

.net is a extremly dangerous thing ;-)

Post 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
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

.net is a extremly dangerous thing ;-)

Post 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
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

.net is a extremly dangerous thing ;-)

Post 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
Post Reply