System.DivideByZeroException
The exception that is thrown when there is an attempt to divide an integral or <code>Decimal</code> value by zero.
Minimum version: >= 1.1 >= Core 1.0
Statistics
How to handle it
try
{
}
catch (System.DivideByZeroException e)
{
}
try
{
}
catch (System.DivideByZeroException e) when (e.Message.Contains("something"))
{
}
try
{
}
catch (System.DivideByZeroException e) when (LogException(e))
{
}
private static bool LogException(Exception e)
{
logger.LogError(...);
return false;
}
How to avoid it
Beforeint dividend = 10;
int divisor = 0;
try
{
int result = dividend / divisor;
}
catch (DivideByZeroException e)
{
}
After
int dividend = 10;
int divisor = 0;
if (divisor > 0)
{
int result = dividend / divisor;
}
Links
YouTube videos
Possible fixes from StackOverflow
You should get all of this by simply calling the .ToString()
method of the exception. We use this to log information and you get everything that I believe you are asking for. See MSDN System.Exception.ToString()
for more information.
The reason of divide by zero here is not really related to truncating result when casting Math.Pow(x, 0)
to int. Math.Pow(x, 0)
will always return 1, and casting it to int will give you 1. Reason is integer overflow. For example consider:
var pow = (int)Math.Pow(10, 10);
10^10 does not fit into int size, so it will overflow (multiple times), and variable pow
will have value -2147483648
. When you multiply that by 10, it again overflows and result is 0. At this point you get your divide by zero exception.
To avoid such bizzare results you might want to do arithmetic operations that might unexpectedly result in overflow in checked context:
checked {
var pow = (int) Math.Pow(10,10);
// throws overflow exception so you can fix your buggy code early
}
Of course at that point you already realize that your algorithm to reverse number is not a good one, so refer to another answer for a better way.
I got something working by emitting an (in-memory) assembly with debug information.
Example code:
var code = @"
var a = 0;
var b = 1 / a;
";
var script = CSharpScript.Create(code);
var compilation = script.GetCompilation();
var ilstream = new MemoryStream();
var pdbstream = new MemoryStream();
compilation.Emit(ilstream, pdbstream);
var assembly = Assembly.Load(ilstream.GetBuffer(), pdbstream.GetBuffer());
var type = assembly.GetType("Submission#0");
var factory = type.GetMethod("<Factory>");
var submissionArray = new object[2];
Task<object> task = (Task<object>)factory.Invoke(null, new object[] { submissionArray });
try
{
await task;
}
catch (DivideByZeroException dbze)
{
Console.WriteLine(dbze.StackTrace);
}
The output is (notice the :line 3
in the stack trace):
at Submission#0.<<Initialize>>d__0.MoveNext() in :line 3
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at UnitTests.ExploreRoslyn.<ExploreEmittingAssembly>d__13.MoveNext() in D:\dev\misc\netmockery\UnitTests\ExploreRoslyn.cs:line 151
Now obviously this is a bit of a hack, and I'm not really happy with the hardcoded script engine implementation details (Submission#0
, <Factory>
), plus I don't really know what I'm doing. There should be (and maybe there is?) a better way.
Update
Created issue https://github.com/dotnet/roslyn/issues/13482 in the Roslyn issue tracker.
There are two issues with your code:
In the first version, you're catching
Exception
, which means that when theAssert.Fail
is reached and throwsAssertionException
, that exception is then caught and ignored.This means that there is no difference between
RunAsync
and delegate here, neither of them throwsDivideByZeroException
.Both
RunAsync
and theScriptRunner<T>
delegate returnTask
. That means to actually wait for them to complete or to observe any exceptions, you need to useawait
. Once you do that, you will see theDivideByZeroException
that you're expecting.
You are encountering limitations of computer-based arithmetic. (Another answer shows the details which I were incorrect in previous versions of my answer.) To avoid these details entirely, you can divide by 10 at the end of each iteration of the loop:
while (x > 0)
{
int endDig = x % 10;
//...
x /= 10;
}
Now you no longer need to worry the limits of int
because your number will never be larger than the original input.
Source: Stack Overflow