0

I have this expression

 long balance = (long)answer.Find(DppGlobals.TAG_TI_BALANCE).Get_QWORD();

which raises exception that there was overflow. The value on the right hand side is of unsigned type and has value: 18446744073708240732.

How to avoid this exception, use unchecked?

PS equivalent C++ implementation returned balance = -1310984, I need same value here too.

Why is there such an exception?


By using unchecked indeed now also on C# side I get -1310984. Can someone advice, am I losing data somehow?

2
  • Well what does the stack trace look like? Is it definitely in the cast? What's the return type of Get_QWord()? (And is there any reason you're violating normal .NET naming conventions with both that and TAG_TI_BALANCE, as an aside?) Without knowing what the code is doing, it's very hard to give good advice. Commented Nov 20, 2015 at 7:09
  • @JonSkeet: Yes I checked it is definitely in the cast. QWORD is ulong. I would appreciate your advice Commented Nov 20, 2015 at 7:13

2 Answers 2

2

Using uncheck will also crop your value, but you will not have an exception,you will get wrong number.I think you will do something changing your code, not mask your exception.

long balance = (unchecked))(long)answer.Find(DppGlobals.TAG_TI_BALANCE).Get_QWORD());

Why is there such an exception?

It is a very good that you get an error.Because if you are working in the sphere where everything is numbers, you can have a mistake and don't understand this.So the RunTime will show you your eror

Sign up to request clarification or add additional context in comments.

16 Comments

Yes using unchecked now I also get -1310984 on C# side. What do you mean it is cropped are you sure?
if its range don't feet into the range of long it will crop your number.So if you have(example for int)a big number and your try to assign it into int variable it will crop the number to fit into the int.So you will get a wrong number
I see bit originally this value was sent as long. Then converted to ulong then again to long as in my question. Why overflow?
because the range of ulong is large than long
@user200312: Well if the value was originally -1310984 then you almost certainly shouldn't have converted it to a ulong to start with... maybe Get_QWORD() should return a long instead.
|
2

Given the comments, it sounds like you do just need to use unchecked arithmetic - but you should be concerned about the use of ulong in your API. If your aim is to just propagate 8 bytes of data, and interpret it as either an unsigned integer or a signed integer depending on context, then you're fine - so long as nothing performs arithmetic on it in the "wrong" form.

It's important to understand why this happens though, and it's much easier to explain that with small numbers. I'll use byte and sbyte as an example. The range of byte is 0 to 255 inclusive. The range of sbyte is -128 to 127 inclusive. Both can store 256 different values. No problem.

Now, using unchecked conversions, it's fine to say:

byte a = GetByteFromSomewhere();
sbyte b = (sbyte) a;
StoreSByteSomewhere(b);
...
sbyte b = GetSByteFromStorage();
byte a = (byte) b;

If that's all you're doing, that's fine. A byte value of -1 will become an sbyte value of 255 and vice versa - basically it's just interpreting the same bit pattern in different ways.

But if you're performing other operations on the value when it's being handled as the "wrong" type, then you could get unexpected answers. For example, consider "dividing by 3". If you divide -9 by 3, you get -3, right? Whereas if you have:

byte original = -9;
sbyte converted = (sbyte) original;
sbyte divided = converted / 3;
byte result = (byte) divided;

... then you end up with a result of -2 instead of -3, due to the way the arithmetic worked.

Now that's all for unchecked conversions. When you have a checked conversion, it doesn't just interpret the bits - it treats the value as a number instead. So for example:

// In a checked context...
byte a = 128;
sbyte b = (sbyte) a; // Bang! Exception

That's because 128 (as a number) is outside the range of sbyte. This is what's happening in your case - the number 18446744073708240732 is outside the range of long, so you're getting an exception. The checked conversion is treating it as a number which can be range-checked, rather than an unchecked conversion just reinterpreting the bits as a long (which leads to the negative number you want).

6 Comments

Dear Jon, it seems I am having hard time to follow your answer fully, can you break it down a bit more? for beginner style? Thank you.
Also, what if I directly have byte a = (byte) GetSByteFromStorage();?
@user200312: It's "hard to break it down" without knowing which bit you're confused by. And yes, casting the result of the method call is exactly equivalent to storing the result in a local variable and then casting that.
@user200312: I've just realized that I haven't included anything about the exception though. Will do that now.
are you sure this byte result = (byte) original; is correct? last line. I am confused when it can result in problem, where does the arithmetic have to occur for me to get wrong results?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.