I'm trying to understand System.Exception class and I got some problems with override function. I try to intercept exception of DivideByZero and Write my user message which I generate in function of derivative class from System.Exception. this is my code:
public class zeroDivision
{
public void Deleter()
{
double z; int i = 0;
try
{
z = 10 / i;
Console.WriteLine("N={0} i={1} Result={2}", 10, i, z);
}
catch (zeroMessage e) **<====problem here: DivideByZeroException**
{
Console.WriteLine("N={0} i={1} Result={2}", 10, i, e.Message);
}
}
}
public class zeroMessage : System.Exception <--here debugger even doesn't come
{
public override string Message
{
get
{
string msg = base.Message;
msg = "Деление на ноль ЗАПРЕЩЕНО!!!";
return msg;
}
}
}
class Program
{
static void Main(string[] args)
{
zeroDivision zero = new zeroDivision();
zero.Deleter();
Console.Read();
}
}
When I call: catch(zeroMessage e) - it unhandled, but if I call: catch(Exception e) - it works. Where is my fault? I don't understand
-------------------------------
After some help of forum's masters, I remade this task with working functions. Maybe it will be useful for anybody:
public class zeroDivision
{
public void Deleter() //First way
{
double z; int i = 0;
try
{
z = 10 / i;
Console.WriteLine("N={0} i={1} Result={2}", 10, i, z);
}
catch (DivideByZeroException)
{
Console.WriteLine("N={0} i={1} Result={2}", 10, i, "Делить на ноль НИЗЗЯ!!!");
}
}
public double Deleter2(int a, int b) //Second way
{
if (b == 0) throw new zeroMessage();
return a / b;
}
public void prn(int i, int j) //Third way
{
try
{
Console.WriteLine(Deleter2(i, j));
}
catch (zeroMessage z)
{
Console.WriteLine(z.Message);
}
}
public void firstDeleter() //Updated Yesterday's code - Forth way
{
double z; int i = 0;
try
{
if (i == 0) throw new zeroMessage(); //!!!
z = 10 / i;
Console.WriteLine("N={0} i={1} Result={2}", 10, i, z);
}
catch (zeroMessage e)
{
Console.WriteLine("N={0} i={1} Result={2}", 10, i, e.Message);
}
}
}
public class zeroMessage : System.Exception
{
public override string Message
{
get
{
string msg = base.Message;
msg = "Деление на ноль ЗАПРЕЩЕНО!!!";
return msg;
}
}
}
class Program
{
static void Main(string[] args)
{
zeroDivision zero = new zeroDivision();
zero.Deleter();
try
{
double result = zero.Deleter2(10, 0);
Console.WriteLine(result);
}
catch (zeroMessage z)
{
Console.WriteLine(z.Message);
}
zeroDivision zero1 = new zeroDivision();
zero1.prn(10, 0);
zeroDivision zero2 = new zeroDivision();
zero2.firstDeleter();
Console.Read();
}
}
When you are trying to divide CLR throws the exception of type DivideByZeroException.
There is no way for CLR to know that you want to throw other exception.
But if you want to play with your new exception, you can do it like this:
public double Divide(int a, int b)
{
if(b == 0) throw new zeroMessage();
return a /b;
}
and use it:
try
{
var result = Divide(10, 0);
}catch(zeroMessage exc)
{
//here you will catch your exception.
}
However there is no sense in such exception, except education goals.
Judging by your code alone, nowhere do you actually throw zeroMessage.
If you want to intercept DivideByZeroException then that is what you have to do.
Get rid of the zeroMessage type, since it has no bearing on the results here, and change the catch code to this:
catch (DivideByZeroException e)
{
...
Note that the code in the runtime will throw exceptions known to the runtime at the time the runtime was compiled. It will not magically pick up that you want to substitute some exceptions for your own. The only way to catch a "x / 0" problem in your code is to catch the DivideByZeroException, not by inventing your own exception type.
Both DivideByZeroException and your zeroMessage class derive from System.Exception. However that doesn´t mean that DivideByZeroException derives from zeroMessage!
What are you trying to achieve? Use System.Exception if you want to catch all possible exceptions, and use DivideByZeroException and the likes, when you are interested in a particular exception like:
double z; int i = 0;
try
{
z = 10 / i;
Console.WriteLine("N={0} i={1} Result={2}", 10, i, z);
}
catch (DivideByZeroException e)
{
Console.WriteLine("N={0} i={1} Result={2}", 10, i, e.Message);
}
catch(Exception e)
{
Console.WriteLine("Unexpected error: ", e.Message);
}
Related
I want to create a method to retry some code with wait when exception occur. How can I get rid of that last exception?
public static T TryWithWait<T>(Func<T> func, int tries, TimeSpan exceptionSleep)
{
if (tries < 1)
throw new Exception("Tries amount cannot be < 1");
for (int i = 0; i < tries; i++)
{
try
{
return func.Invoke();
}
catch
{
if (i == (tries - 1))
throw;
else
Thread.Sleep(exceptionSleep);
}
}
throw new Exception("Code wouldn't compile without that");
}
You can use recursivity !
public static T TryWithWait<T>(Func<T> func, int tries, TimeSpan exceptionSleep, Exception innerException = null)
{
// You must to knows what exception was generated, I put it as InnerException
if (tries < 1) throw new Exception("Tries amount cannot be < 1", innerException);
try
{
return func.Invoke();
}
catch(Exception exception)
{
return TryWithWait(func, --tries, exceptionSleep, exception);
}
}
This question already has answers here:
Why does this string extension method not throw an exception?
(3 answers)
Closed 7 years ago.
I just had a case with a method using yield return not throwing an ArgumentException which I expected. I have reconstructed the case with the simpliest possible classes here:
class Program
{
static void Main(string[] args)
{
try
{
var listA = FooA(count: 0);
Console.WriteLine("A did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("A threw exception!");
}
try
{
var listB = FooB(count: 0);
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
Console.ReadLine();
}
private static IEnumerable<int> FooA(int count)
{
if(count == 0)
throw new ArgumentException("Count must be above 0");
var list = new List<int>();
for (var i = 0; i < count; i++)
{
list.Add(i);
}
return list;
}
private static IEnumerable<int> FooB(int count)
{
if (count == 0)
throw new ArgumentException("Count must be above 0");
for (var i = 0; i < count; i++)
{
yield return i;
}
}
}
Output:
A threw exception!
B did not throw exception!
Can some one please explain to me why FooB does not throw an exception while FooA does?
It's because FooB is never even evaluated.
When you call a method, that method is called immediately. When you use yield and return an enumerable, that method is only called when something needs to use the value returned, and only a single item at a time; this is the benefit of yielding.
So, if you add something that uses the value
try
{
var listB = FooB(count: 0);
Console.WriteLine(listB.First()); // use the IEnumerable returned
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
You will see your expected result.
This function should find the longest file in a path it get as parameter.
It seems to work well the problem is I’m not sure how to handle exceptions.
In case of PathTooLongException I want to set _MaxPath to -2 and exit the function, in case of other exception set it to -1 and exit the function else set it to longest file path.
I'm not sure what is the right way to handle exceptions in that case.
Probably a dumb question but I’m new with C#...
static int _MaxPath = 0;
public static void GetLongestFilePath(string p)
{
try
{
foreach (string d in Directory.GetDirectories(p))
{
foreach (string f in Directory.GetFiles(d))
{
if (f.Length > _MaxPath)
{
_MaxPath = f.Length;
}
}
GetLongestFilePath(d);
}
}
catch (Exception e)
{
if (e is PathTooLongException)
{
_MaxPath = -1;
}
}
finally
{
System.Environment.Exit(-99);
}
}
You can have multiple catch blocks with multiple Exception types:
try
{
// ...
}
catch (PathTooLongException e)
{
_MaxPath = -2;
return;
}
catch (Exception e) //anything else
{
_MaxPath = -1;
// ...
}
finally
{
// ...
}
You can catch the specific exception type in its own block:
static int _MaxPath = 0;
public static void GetLongestFilePath(string p)
{
try
{
foreach (string d in Directory.GetDirectories(p))
{
foreach (string f in Directory.GetFiles(d))
{
if (f.Length > _MaxPath)
{
_MaxPath = f.Length;
}
}
GetLongestFilePath(d);
}
}
catch (PathTooLongException e)
{
_MaxPath = -2;
}
catch (Exception e)
{
_MaxPath = -1;
}
finally
{
System.Environment.Exit(-99);
}
}
This question already has answers here:
Why does this string extension method not throw an exception?
(3 answers)
Closed 7 years ago.
I just had a case with a method using yield return not throwing an ArgumentException which I expected. I have reconstructed the case with the simpliest possible classes here:
class Program
{
static void Main(string[] args)
{
try
{
var listA = FooA(count: 0);
Console.WriteLine("A did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("A threw exception!");
}
try
{
var listB = FooB(count: 0);
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
Console.ReadLine();
}
private static IEnumerable<int> FooA(int count)
{
if(count == 0)
throw new ArgumentException("Count must be above 0");
var list = new List<int>();
for (var i = 0; i < count; i++)
{
list.Add(i);
}
return list;
}
private static IEnumerable<int> FooB(int count)
{
if (count == 0)
throw new ArgumentException("Count must be above 0");
for (var i = 0; i < count; i++)
{
yield return i;
}
}
}
Output:
A threw exception!
B did not throw exception!
Can some one please explain to me why FooB does not throw an exception while FooA does?
It's because FooB is never even evaluated.
When you call a method, that method is called immediately. When you use yield and return an enumerable, that method is only called when something needs to use the value returned, and only a single item at a time; this is the benefit of yielding.
So, if you add something that uses the value
try
{
var listB = FooB(count: 0);
Console.WriteLine(listB.First()); // use the IEnumerable returned
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
You will see your expected result.
Im getting a stackoverflow exception when i'm filling the ellipse not just one ellipse but many ellipses.
I dont think it is a problem from the graphics creator. But i can't figure out why the debugger is pointing a stackoverflow exception at the FillEllipse command
public void createPath(Stance currentStance)
{
if(toSort.Count > 0)
{
toSort.Remove(currentStance);
counter++;
}
this.currentForm.FillEllipse(new SolidBrush(Color.Red),new Rectangle(currentStance.location.X-3, currentStance.location.Y - 3, 6 , 6));
foreach(Stance subStance in currentStance.childStances)
{
double weight = level(currentStance, subStance, 1)+ currentStance.StanceWeight;
if (subStance.StanceWeight == -99999999999999)
{
currentStance.dajkstrasChildren.Add(subStance);
subStance.parentStance = currentStance;
subStance.StanceWeight = weight;
toSort.Add(subStance);
}
else
{
if(weight > subStance.StanceWeight)
{
try
{
subStance.parentStance.dajkstrasChildren.Remove(subStance);
}
catch (NullReferenceException e)
{
Console.WriteLine("null reference");
}
subStance.parentStance = currentStance;
currentStance.dajkstrasChildren.Add(subStance);
subStance.StanceWeight = weight;
}
}
}
foreach(Stance subStance in currentStance.secondChildStances)
{
double weight = level(currentStance, subStance, 1) + currentStance.StanceWeight;
if (subStance.StanceWeight == -99999999999999)
{
currentStance.dajkstrasChildren.Add(subStance);
subStance.parentStance = currentStance;
toSort.Add(subStance);
subStance.StanceWeight = weight;
}
else
{
if (weight > subStance.StanceWeight)
{
if(subStance.parentStance != null)
{
try
{
subStance.parentStance.dajkstrasChildren.Remove(subStance);
subStance.parentStance = currentStance;
currentStance.dajkstrasChildren.Add(subStance);
}
catch(NullReferenceException e)
{
Console.WriteLine("null reference");
}
}
}
}
}
toSort.Sort(new Stance());
if(toSort.Count != 0)
{
createPath((Stance)toSort[0]);
}
}
it is a recursive method but it cant recurse to infinity as it always pops a single object from the toSort ArrayList
That's because it is in the attempt to make the call to FillEllipse that the stack actually runs out.
Of course the stack overflow has to be caused by a flaw in your logic that causes your createPath method to be called recursively either (probably) indefinitely or too deeply for the stack to accommodate all the needed activation frames.
Use a while loop instead of recursion to avoid loading up the stack.
Here is your code modified that might work:
public void createPath(Stance stance)
{
var currentStance = stance;
while(toSort.Count >0)
{
toSort.Remove(currentStance);
counter++;
this.currentForm.FillEllipse(new SolidBrush(Color.Red),new Rectangle(currentStance.location.X-3, currentStance.location.Y - 3, 6 , 6));
foreach(Stance subStance in currentStance.childStances)
{
double weight = level(currentStance, subStance, 1)+ currentStance.StanceWeight;
if (subStance.StanceWeight == -99999999999999)
{
currentStance.dajkstrasChildren.Add(subStance);
subStance.parentStance = currentStance;
subStance.StanceWeight = weight;
toSort.Add(subStance);
}
else
{
if(weight > subStance.StanceWeight)
{
try
{
subStance.parentStance.dajkstrasChildren.Remove(subStance);
}
catch (NullReferenceException e)
{
Console.WriteLine("null reference");
}
subStance.parentStance = currentStance;
currentStance.dajkstrasChildren.Add(subStance);
subStance.StanceWeight = weight;
}
}
}
foreach(Stance subStance in currentStance.secondChildStances)
{
double weight = level(currentStance, subStance, 1) + currentStance.StanceWeight;
if (subStance.StanceWeight == -99999999999999)
{
currentStance.dajkstrasChildren.Add(subStance);
subStance.parentStance = currentStance;
toSort.Add(subStance);
subStance.StanceWeight = weight;
}
else
{
if (weight > subStance.StanceWeight)
{
if(subStance.parentStance != null)
{
try
{
subStance.parentStance.dajkstrasChildren.Remove(subStance);
subStance.parentStance = currentStance;
currentStance.dajkstrasChildren.Add(subStance);
}
catch(NullReferenceException e)
{
Console.WriteLine("null reference");
}
}
}
}
}
toSort.Sort(new Stance());
currentStance = (Stance)toSort[0];
}
}