Checked Block vs Try Block [duplicate] - c#

I just came across this keyword for the first time. What does it do, and when should it be used?
int multiply(int i, int j)
{
return checked(i * j);
}

Eric Lippert has a two-part blog post "What is the unchecked keyword good for?": Part 1 -- Part 2
"Checked" is a block keyword that enables arithmetic overflow checking. Normally, if an integer operation exceeds the maximum or minimum value that the type can handle, the operation proceeds anyway, and the result just cycles like an odometer. So, for example:
byte b = byte.MaxValue;
Console.WriteLine(b); // 255 (11111111)
Console.WriteLine(++b); // 0 (00000000)
Placing this snippet in a checked block prevents the overflow, and instead the runtime throws an OverflowException:
checked
{
byte b = byte.MaxValue;
Console.WriteLine(b); // b=255
try
{
Console.WriteLine(++b);
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // "Arithmetic operation resulted in an overflow."
// b = 255
}
}
And since there's a compiler option /checked, which turns compiler checking on by default, there is also the unchecked keyword which prevents overflow checking.
As far as usage, overflow checking should be used sparingly, as is true of exception handling in general. To check for an overflow at runtime, it's significantly faster (like, an order of magnitude) to do a simple check, rather than to turn on overflow checking:
int multiply(int i, int j)
{
if ((long)i * (long)j > int.MaxValue)
throw new InvalidOperationException("overflow");
return i*j;
}
You can do this even for Int64/long, using BigInteger (this can be still at least an order of magnitude faster than using checked):
long multiply(long i, long j)
{
if (new System.Numerics.BigInteger(i) + j > long.MaxValue)
throw new InvalidOperationException("overflow");
return i*j;
}
There's also a good Code Project article on this that explains some caveats (eg, the overflow check only applies to the immediate code block, not to any function calls inside the block).

Related

Can Interlocked CompareExchange be used correctly in this multithreaded round-robin implementation?

I need to round-robin some calls between N different connections because of some rate limits in a multithreaded context. I've decided to implement this functionality using a list and a "counter," which is supposed to "jump by one" between instances on each call.
I'll illustrate this concept with a minimal example (using a class called A to stand in for the connections)
class A
{
public A()
{
var newIndex = Interlocked.Increment(ref index);
ID = newIndex.ToString();
}
private static int index;
public string ID;
}
static int crt = 0;
static List<A> Items = Enumerable.Range(1, 15).Select(i => new A()).ToList();
static int itemsCount = Items.Count;
static A GetInstance()
{
var newIndex = Interlocked.Increment(ref crt);
var instance = Items[newIndex % itemsCount];
//Console.WriteLine($"{DateTime.Now.Ticks}, {Guid.NewGuid()}, Got instance: {instance.ID}");
return instance;
}
static void Test()
{
var sw = Stopwatch.StartNew();
var tasks = Enumerable.Range(1, 1000000).Select(i => Task.Run(GetInstance)).ToArray();
Task.WaitAll(tasks);
}
This works as expected in that it ensures that calls are round-robin-ed between the connections. I will probably stick to this implementation in the "real" code (with a long instead of an int for the counter)
However, even if it is unlikely to reach int.MaxValue in my use case, I wondered if there is a way to "safely overflow" the counter.
I know that "%" in C# is "Remainder" rather than "Modulus," which would mean that some ?: gymnastics would be required to always return positives, which I want to avoid.
So what I wanted to cume up with is instead something like:
static A GetInstance()
{
var newIndex = Interlocked.Increment(ref crt);
Interlocked.CompareExchange(ref crt, 0, itemsCount); //?? the return value is the original value, how to know if it succeeded
var instance = Items[newIndex];
//Console.WriteLine($"{DateTime.Now.Ticks}, {Guid.NewGuid()}, Got instance: {instance.ID}");
return instance;
}
What I am expecting is that Interlocked.CompareExchange(ref crt, 0, itemsCount) would be "won" by only one thread, setting the counter back to 0 once it reaches the number of connections available. However, I don't know how to use this in this context.
Can CompareExchange or another mechanism in Interlocked be used here?
You could probably:
static int crt = -1;
static readonly IReadOnlyList<A> Items = Enumerable.Range(1, 15).Select(i => new A()).ToList();
static readonly int itemsCount = Items.Count;
static readonly int maxItemCount = itemsCount * 100;
static A GetInstance()
{
int newIndex;
while (true)
{
newIndex = Interlocked.Increment(ref crt);
if (newIndex >= itemsCount)
{
while (newIndex >= itemsCount && Interlocked.CompareExchange(ref crt, -1, newIndex) != newIndex)
{
// There is an implicit memory barrier caused by the Interlockd.CompareExchange around the
// next line
// See for example https://afana.me/archive/2015/07/10/memory-barriers-in-dot-net.aspx/
// A full memory barrier is the strongest and interesting one. At least all of the following generate a full memory barrier implicitly:
// Interlocked class mehods
newIndex = crt;
}
continue;
}
break;
}
var instance = Items[newIndex % itemsCount];
//Console.WriteLine($"{DateTime.Now.Ticks}, {Guid.NewGuid()}, Got instance: {instance.ID}");
return instance;
}
But I have to say the truth... I'm not sure if it is correct (it should be), and explaining it is hard, and if anyone touches it in any way it will break.
The basic idea is to have a "low" ceiling for crt (we don't want to overflow, it would break everything... so we want to keep veeeeeery far from int.MaxValue, or you could use uint).
The maximum possible value is:
maxItemCount = (int.MaxValue - MaximumNumberOfThreads) / itemsCount * itemsCount;
The / itemsCount * itemsCount is because we want the rounds to be equally distributed. In the example I give I use a probably much lower number (itemsCount * 100) because lowering this ceiling will only cause the reset more often, but the reset isn't so much slow that it is truly important (it depends on what you are doing on the threads. If they are very small threads that only use cpu then the reset is slow, but if not then it isn't).
Then when we overflow this ceiling we try to move it back to -1 (our starting point). We know that at the same time other bad bad threads could Interlocked.Increment it and create a race on this reset. Thanks to the Interlocked.CompareExchange only one thread can successfully reset the counter, but the other racing threads will immediately see this and break from their attempts.
Mmmh... The if can be rewritten as:
if (newIndex >= itemsCount)
{
int newIndex2;
while (newIndex >= itemsCount && (newIndex2 = Interlocked.CompareExchange(ref crt, 0, newIndex)) != newIndex)
{
// If the Interlocked.CompareExchange is successfull, the while will end and so we won't be here,
// if it fails, newIndex2 is the current value of crt
newIndex = newIndex2;
}
continue;
}
No, the Interlocked class offers no mechanism that would allow you to restore an Int32 value back to zero in case it overflows. The reason is that it is possible for two threads to invoke concurrently the var newIndex = Interlocked.Increment(ref crt); statement, in which case both with overflow the counter, and then none will succeed in updating the value back to zero. This functionality is just beyond the capabilities of the Interlocked class. To make such complex operations atomic you'll need to use some other synchronization mechanism, like a lock.
Update: xanatos's answer proves that the above statement is wrong. It is also proven wrong by the answers of this 9-year old question. Below are two implementation of an InterlockedIncrementRoundRobin method. The first is a simplified version of this answer, by Alex Sorokoletov:
public static int InterlockedRoundRobinIncrement(ref int location, int modulo)
{
// Arguments validation omitted (the modulo should be a positive number)
uint current = unchecked((uint)Interlocked.Increment(ref location));
return (int)(current % modulo);
}
This implementation is very efficient, but it has the drawback that the backing int value is not directly usable, since it circles through the whole range of the Int32 type (including negative values). The usable information comes by the return value of the method itself, which is guaranteed to be in the range [0..modulo]. If you want to read the current value without incrementing it, you would need another similar method that does the same int -> uint -> int conversion:
public static int InterlockedRoundRobinRead(ref int location, int modulo)
{
uint current = unchecked((uint)Volatile.Read(ref location));
return (int)(current % modulo);
}
It also has the drawback that once every 4,294,967,296 increments, and unless the modulo is a power of 2, it returns a 0 value prematurely, before having reached the modulo - 1 value. In other words the rollover logic is technically flawed. This may or may not be a big issue, depending on the application.
The second implementation is a modified version of xanatos's algorithm:
public static int InterlockedRoundRobinIncrement(ref int location, int modulo)
{
// Arguments validation omitted (the modulo should be a positive number)
while (true)
{
int current = Interlocked.Increment(ref location);
if (current >= 0 && current < modulo) return current;
// Overflow. Try to zero the number.
while (true)
{
int current2 = Interlocked.CompareExchange(ref location, 0, current);
if (current2 == current) return 0; // Success
current = current2;
if (current >= 0 && current < modulo)
{
break; // Another thread zeroed the number. Retry increment.
}
}
}
}
This is slightly less efficient (especially for small modulo values), because once in a while an Interlocked.Increment operation results to an out-of-range value, and the value is rejected and the operation repeated. It does have the advantage though that the backing int value remains in the [0..modulo] range, except for some very brief time spans, during some of this method's invocations.
An alternative to using CompareExchange would be to simply let the values overflow.
I have tested this and could not prove it wrong (so far), but of course that does not mean that it isn't.
//this incurs some cost, but "should" ensure that the int range
// is mapped to the unit range (int.MinValue is mapped to 0 in the uint range)
static ulong toPositive(int i) => (uint)1 + long.MaxValue + (uint)i;
static A GetInstance()
{
//this seems to overflow safely without unchecked
var newCounter = Interlocked.Increment(ref crt);
//convert the counter to a list index, that is map the unsigned value
//to a signed range and get the value modulus the itemCount value
var newIndex = (int)(toPositive(newCounter) % (ulong)itemsCount);
var instance = Items[newIndex];
//Console.WriteLine($"{DateTime.Now.Ticks}, Got instance: {instance.ID}");
return instance;
}
PS: Another part of the xy problem part of my question: At a friend's suggestion I am currently investigating using a LinkedList or something similar (with locks) to achieve the same purpose.

Overflow exception double into int

In debugging mode this line of code double divided by int result in an System.Overflow exception. The value for the int32 was too small/large.
The result of 0.0d/0 is NaN. Which does not fit into a int obviously.
int result = Convert.ToInt32(0.0d/0);
But how do I handle that scenario correctly that no exception happens? Or should I try catch it?
The byte size of an int is too small to fit all possible double values. See Data Types. Your best option is to carry out the conversion in a try-block and catch the OverflowException.
try
{
int result = Convert.ToInt32(0.0d/0);
}
catch (OverflowException)
{
//...
}
I'd say that depends entirely on your applications expectations.
If you know the double can be NaN or just larger than Int32.MaxValue and you like the function to continue with a specific result, you should write a check.
If an overflow is an actual exception that needs to be handled up-stack by some special logic, you should throw an exception.
You know what this calculation is supposed to calculate, so you should be already able to decide if 'NaN' is OK and what should be put into that int when such result occurs. You may catch it. You may add ifs to make sure it doesnt happen. You may leave it. You may do whatever you need, but first, you need to decide what you want to occur when a 0.0 happens. It is there for some reason.
Seeing 0.0/0.0 usually mean an error earlier in the code. 0/0 almost never makes sense, hence Not-a-Number is the result to remind about it.
In general, you may want to trace and diagnose why the division-by-zero occurred. Check why the second variable is zero (why was that /0.0 and not i.e. /1.0 ?), decide if it is a valid possible value and if it is not OK then fix the code responsible for that zero, so zero won't occur at all.
For instance, if you had a formula forcepower(x,z) / distance(x,z) and both the power and the distance turned out to be zeros because x and z were the same point, then you may add an if checking x==z and force the result to be 0.0 in such case. But, if that formula calculated foobarized whachamacallit then you should pick the most frublastic number. I don't know. You should.
---edit
Ok, after your comments I understand it now. So you've got control over all values that are used in division - good!
Since you already test 'bar' for zero and in this case force 'foo' to zero (I've seen your comment about 'because nothing can be calculated then') then the problem is in fact in the way you have designed, or, 'encoded' the results.
Forcing something to 0.0 or 0 isn't a really good way of indicating that "nothing was calculated". In later parts of the code you will have a hard time telling if the bazz is 0 because it was the result, or because it was not calculated.
Sure, of course, if 0 is an actually invalid value that normally can never occur, then its sometimes ok to use it as a special "nothing"-indicating value..
..but as you saw from that 0/0 case, it can cause inobvious problems, and also it will force you to remember to check in every place if 'values are good':
double foo;
if(bar != 0) foo = calculate_the_foo(); // check the Bar maybe it's zero
else foo = 0.0; // can't calculate, no foo
double z;
if(bar != 0) z = foo/bar; // added a check against zero in bar again..
else z = ...um? what to use here.. 0 again?
int result = Convert.ToInt32(z);
// later in the code
if(result != 0) //..again? but.. is it result of 0 or no result?
..
// and so on
It is very easy to forget to check for special values and to simply write result = foo/bar and get Infinites, NaNs or Overflows.
Therefore, it is much better to use a 0 to really mean normal zero and to use a proper no-value thing for indicating a missing data..
..and the simplest one is plain old ... null.
If you use nullables like int? or double?, then you can simply write things like:
using System.IO;
using System;
class Program
{
static void Main()
{
double? foo = 5.0;
double? bar = 4.0;
double? result = foo/bar;
Console.WriteLine("x/y: " + prettynulls(result));
// ^writes: 1.25
foo = null;
bar = 4.0;
result = foo/bar;
Console.WriteLine("null/y: " + prettynulls(result));
// ^writes: (null)
foo = 5.0;
bar = null;
result = foo/bar;
Console.WriteLine("x/null: " + prettynulls(result));
// ^writes: (null)
foo = null;
bar = null;
result = foo/bar;
Console.WriteLine("null/null: " + prettynulls(result));
// ^writes: (null)
}
private static string prettynulls(double? val)
{
return val == null ? "(null)" : val.ToString();
}
}
Please observe that you can even do operations like +-/* on them without tons of ifs to check for nulls. Mathematic operations simply will return null if one operand was null. Hence your case would become:
double? foo;
if( ... ) foo = calculate_the_foo();
else foo = null;
int? result = (int?)( foo/bar );
of by making the calculate smart with nullables when foo can't be calculated:
double? foo = calculate_the_foo();
int? result = (int?)( foo/bar );
Look at the simplicity and expressiveness. Nullables like double? even handle casting. A double? that holds a null, when casted to int? will simply be return null. Otherwise it will cast the double value to int and return int.

What is the C# "checked" keyword for?

I just came across this keyword for the first time. What does it do, and when should it be used?
int multiply(int i, int j)
{
return checked(i * j);
}
Eric Lippert has a two-part blog post "What is the unchecked keyword good for?": Part 1 -- Part 2
"Checked" is a block keyword that enables arithmetic overflow checking. Normally, if an integer operation exceeds the maximum or minimum value that the type can handle, the operation proceeds anyway, and the result just cycles like an odometer. So, for example:
byte b = byte.MaxValue;
Console.WriteLine(b); // 255 (11111111)
Console.WriteLine(++b); // 0 (00000000)
Placing this snippet in a checked block prevents the overflow, and instead the runtime throws an OverflowException:
checked
{
byte b = byte.MaxValue;
Console.WriteLine(b); // b=255
try
{
Console.WriteLine(++b);
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // "Arithmetic operation resulted in an overflow."
// b = 255
}
}
And since there's a compiler option /checked, which turns compiler checking on by default, there is also the unchecked keyword which prevents overflow checking.
As far as usage, overflow checking should be used sparingly, as is true of exception handling in general. To check for an overflow at runtime, it's significantly faster (like, an order of magnitude) to do a simple check, rather than to turn on overflow checking:
int multiply(int i, int j)
{
if ((long)i * (long)j > int.MaxValue)
throw new InvalidOperationException("overflow");
return i*j;
}
You can do this even for Int64/long, using BigInteger (this can be still at least an order of magnitude faster than using checked):
long multiply(long i, long j)
{
if (new System.Numerics.BigInteger(i) + j > long.MaxValue)
throw new InvalidOperationException("overflow");
return i*j;
}
There's also a good Code Project article on this that explains some caveats (eg, the overflow check only applies to the immediate code block, not to any function calls inside the block).

Best way to handle Integer overflow in C#?

Handling integer overflow is a common task, but what's the best way to handle it in C#? Is there some syntactic sugar to make it simpler than with other languages? Or is this really the best way?
int x = foo();
int test = x * common;
if(test / common != x)
Console.WriteLine("oh noes!");
else
Console.WriteLine("safe!");
I haven't needed to use this often, but you can use the checked keyword:
int x = foo();
int test = checked(x * common);
Will result in a runtime exception if overflows. From MSDN:
In a checked context, if an expression produces a value that is
outside the range of the destination type, the result depends on
whether the expression is constant or non-constant. Constant
expressions cause compile time errors, while non-constant expressions
are evaluated at run time and raise exceptions.
I should also point out that there is another C# keyword, unchecked, which of course does the opposite of checked and ignores overflows. You might wonder when you'd ever use unchecked since it appears to be the default behavior. Well, there is a C# compiler option that defines how expressions outside of checked and unchecked are handled: /checked. You can set it under the advanced build settings of your project.
If you have a lot of expressions that need to be checked, the simplest thing to do would actually be to set the /checked build option. Then any expression that overflows, unless wrapped in unchecked, would result in a runtime exception.
Try the following
int x = foo();
try {
int test = checked (x * common);
Console.WriteLine("safe!");
} catch (OverflowException) {
Console.WriteLine("oh noes!");
}
The best way is as Micheal Said - use Checked keyword.
This can be done as :
int x = int.MaxValue;
try
{
checked
{
int test = x * 2;
Console.WriteLine("No Overflow!");
}
}
catch (OverflowException ex)
{
Console.WriteLine("Overflow Exception caught as: " + ex.ToString());
}
Sometimes, the simplest way is the best way. I can't think a better way to write what you wrote, but you can short it to:
int x = foo();
if ((x * common) / common != x)
Console.WriteLine("oh noes!");
else
Console.WriteLine("safe!");
Note that I didn't remove the x variable because it'd be foolish to call the foo() three times.
Old thread, but I just ran into this. I didn't want to use exceptions. What I ended up with was:
long a = (long)b * (long)c;
if(a>int.MaxValue || a<int.MinValue)
do whatever you want with the overflow
return((int)a);
So, I ran into this far after the fact, and it mostly answered my question, but for my particular case (in the event anyone else has the same requirements), I wanted anything that would overflow the positive value of a signed int to just settle at int.MaxValue:
int x = int.MaxValue - 3;
int someval = foo();
try
{
x += someval;
}
catch (OverflowException)
{
x = int.MaxValue;
}

How do I gracefully test for overflow situations in C#?

Update: I'm going to leave it as is: The performance hit of a exception (very rare) is better than the probably performance hit for checking on each operation (common)
I'm trying to support an "EstimatedRowCount" that in one case would be the product of two sub-cursors that are joined together:
estimatedRowCount = left.EstimatedRowCount * right.EstimatedRowCount;
return estimatedRowCount;
Of course, if left and right are big enough, this will throw an OverflowException.
Here, I don't really care if estimatedRowCount is 100% accurate, just big enough to know that this cursor is holding a lot of data.
Right now, I'm doing this:
// We multiply our rowcount
Int64 estimRowCount = 0;
try
{
estimRowCount = leftRowCount * rightRowCount;
}
catch (OverflowException)
{
// Ignore overflow exceptions
estimRowCount = Int64.MaxValue;
}
return estimRowCount;
Is there a better way to test for overflow operations so I don't have to do the try{}catch to guard?
This sounds like a good use case for the 'unchecked' keyword.
To use, simply wrap your assignment in an 'unchecked' block:
Int64 estimRowCount = 0;
unchecked
{
estimRowCount = leftRowCount * rightRowCount;
}
Then test to see if the result is negative - if it is, it overflowed:
if (estimRowCount > 0) estimRowCount = Int64.MaxValue;
You'll need to ensure in this case that neither leftRowCount nor rightRowCount can be negative, but given the context I don't think that'll occur.
if (Int64.MaxValue / leftRowCount <= rightRowCount)
{
estimRowCount = leftRowCount * rightRowCount
}
else
{
estimRowCount = Int64.MaxValue;
}
Not sure if I could explain myself without an editor.
But, I hope you get the idea.
Your solution seems quite reasonable. Is there something specific you want to optimize? Does that product cause the overflow condition so frequently that you're worried about the performance hit of the exception handling?
(Just simple food for thought, if leftRowCount and rightRowCount are Int32, not Int64, then your product cannot overflow your Int64 estimRowCount lvalue.)

Categories