✅ Exception handling..

namespace Calculator.Model
{
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException();
}

return number1 / number2;
}

}
}
namespace Calculator.Model
{
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException();
}

return number1 / number2;
}

}
}
When the method Run encounters an instance where number2 == 0 i want it to throw an exception BUT i dont want the program to stop. How does that work?
53 Replies
Jimmacle
Jimmacle3w ago
not sure what you mean the calling code has to handle the exception with a try/catch
Angius
Angius3w ago
You have to catch that exception Otherwise, the program will crash
Merineth 🇸🇪
So i have to make a try/catch on the call to run?
Angius
Angius3w ago
ye
Jimmacle
Jimmacle3w ago
yes or somewhere in that call stack so the exception gets caught at some point
Merineth 🇸🇪
Right, that does make sense but Ugh it's so hard to explain
public static void ZeroInputArgument()
{
while (true)
{

Console.WriteLine("Enter an RPN expression <return> (empty string = exit):");
string input = Console.ReadLine();

// If the input from the user is an empty string, i.e the user pressed Enter. It will close the program.
if (input == "")
{
System.Environment.Exit(1);
}

//Vi borde göra om följade till en token klass så att vi inte måste göra detta
//varenda gång i både zero och two input argument och istället bara kan göra det i en klass.

//Jag tänker att vi gör en ny klass, typ tokenize, som omvanldlar en

//härifrån
string[] tokens = input.Split(' ');
Mystack stack = new Mystack();
stack.Fill(tokens);

string top = stack.pop();

CalculationHandler calculationHandler = new CalculationHandler(stack);
//hit

decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
public static void ZeroInputArgument()
{
while (true)
{

Console.WriteLine("Enter an RPN expression <return> (empty string = exit):");
string input = Console.ReadLine();

// If the input from the user is an empty string, i.e the user pressed Enter. It will close the program.
if (input == "")
{
System.Environment.Exit(1);
}

//Vi borde göra om följade till en token klass så att vi inte måste göra detta
//varenda gång i både zero och two input argument och istället bara kan göra det i en klass.

//Jag tänker att vi gör en ny klass, typ tokenize, som omvanldlar en

//härifrån
string[] tokens = input.Split(' ');
Mystack stack = new Mystack();
stack.Fill(tokens);

string top = stack.pop();

CalculationHandler calculationHandler = new CalculationHandler(stack);
//hit

decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
In this code here, down towards the bottom we call the decimal output = calculationHandler.Run(top); I could make a try/catch here HOWEVER in the output they expect me to list the numbers i'ts trying to divide with. And they are defined elsewhere e.g 4 0 / should result in console output Exception: Divide by zero: 4,00/0,00`
Jimmacle
Jimmacle3w ago
so put that information in your custom exception and access it in the catch to print that message exceptions are just classes, they can hold whatever data you want
Merineth 🇸🇪
I can do that?
Angius
Angius3w ago
So?
try {
var res = Run();
Console.WriteLine($"{a} {sig} {b} = {res}");
}
catch(Exception e)
{
Console.WriteLine($"a = {a}, b = {b} produces {e.Message}");
}
try {
var res = Run();
Console.WriteLine($"{a} {sig} {b} = {res}");
}
catch(Exception e)
{
Console.WriteLine($"a = {a}, b = {b} produces {e.Message}");
}
Or some such Or, yeah, put that info in the exception
Merineth 🇸🇪
Can my custom exception print it out?
Angius
Angius3w ago
Exceptions don't "run" So they cannot print You can catch that exception and print whatever's stored in it
Merineth 🇸🇪
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException(number1, number2);
}
return number1 / number2;
}

}
}
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException(number1, number2);
}
return number1 / number2;
}

}
}
Ok so in my division class, if the number2 == 0 i throw a new custom exception with those two numbers
Angius
Angius3w ago
For example, yeah
Merineth 🇸🇪
Visual studio made it for me but
public class AlexDivideByZeroException : Exception
{
private decimal number1;
private decimal number2;

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
public class AlexDivideByZeroException : Exception
{
private decimal number1;
private decimal number2;

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
Seems right?
Pobiega
Pobiega3w ago
Not quite
Angius
Angius3w ago
It's private How you gonna access that from the outside? Make those private fields into public properties Can be get-only
Pobiega
Pobiega3w ago
Yep, and maybe call the base constructor to set a message
Merineth 🇸🇪
Hold on this is a lot
public class AlexDivideByZeroException : Exception
{
public decimal number1;
public decimal number2;

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
public class AlexDivideByZeroException : Exception
{
public decimal number1;
public decimal number2;

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
What is the method meant to do?
Angius
Angius3w ago
What method? The constructor? It's... the constructor It's what gets called when you new that thing up
Merineth 🇸🇪
haha this course has been so goddamn rushed
MODiX
MODiX3w ago
Angius
REPL Result: Success
class Foo
{
public Foo(string s)
{
Console.WriteLine($"Henlo {s}!");
}
}

var f = new Foo("world");
class Foo
{
public Foo(string s)
{
Console.WriteLine($"Henlo {s}!");
}
}

var f = new Foo("world");
Console Output
Henlo world!
Henlo world!
Compile: 484.101ms | Execution: 33.981ms | React with ❌ to remove this embed.
Merineth 🇸🇪
i feel so overwhelmed How's that a constructor. I was told that is a method.
Angius
Angius3w ago
Look closely It has no return type
Merineth 🇸🇪
ah..
Angius
Angius3w ago
And it has the same name as the class It's a constructor $structure
MODiX
MODiX3w ago
namespace Namespace;

[Attribute]
public class Class
{
public string PublicField;
private bool _privateField;

public int PublicProperty { get; set; }

public Class() {} // Constructor

public void Method(int parameter)
{
var localVariable = parameter;

int LocalMethod(string param) { return 3; }
}
}
namespace Namespace;

[Attribute]
public class Class
{
public string PublicField;
private bool _privateField;

public int PublicProperty { get; set; }

public Class() {} // Constructor

public void Method(int parameter)
{
var localVariable = parameter;

int LocalMethod(string param) { return 3; }
}
}
Merineth 🇸🇪
So constructors are methods without a return type. They just create an object of what's inside the {}?
Angius
Angius3w ago
They let you do the initial setup of the class, basically In your example, the code you sent, it prevents you from ever creating an instance that would not have those two numbers
MODiX
MODiX3w ago
Angius
REPL Result: Failure
class Foo
{
private int _bar;
public Foo(int bar)
{
_bar = bar;
}
}

var f = new Foo(); // error
class Foo
{
private int _bar;
public Foo(int bar)
{
_bar = bar;
}
}

var f = new Foo(); // error
Exception: CompilationErrorException
- There is no argument given that corresponds to the required parameter 'bar' of 'Foo.Foo(int)'
- There is no argument given that corresponds to the required parameter 'bar' of 'Foo.Foo(int)'
Compile: 272.814ms | Execution: 0.000ms | React with ❌ to remove this embed.
Angius
Angius3w ago
One of two ways to ensure the instance will be given all the necessary data when created
Merineth 🇸🇪
Yes ok but
public class AlexDivideByZeroException : Exception
{
public decimal number1 { get; }
public decimal number2 { get; }

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
public class AlexDivideByZeroException : Exception
{
public decimal number1 { get; }
public decimal number2 { get; }

public AlexDivideByZeroException(decimal number1, decimal number2)
{
this.number1 = number1;
this.number2 = number2;
}
}
}
` I created my exception for it now
Angius
Angius3w ago
Yep, this will work
Pobiega
Pobiega3w ago
yep, starting to look good
Angius
Angius3w ago
The naming does not adhere fully to C# standards, but whatever It will do
Merineth 🇸🇪
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException(number1, number2);
}
return number1 / number2;
}
internal class Division
{
public decimal Run(decimal number1, decimal number2)
{
if (number2 == 0)
{
throw new AlexDivideByZeroException(number1, number2);
}
return number1 / number2;
}
And in my Division class i throw that exception?
Angius
Angius3w ago
Yep
Pobiega
Pobiega3w ago
so far so good
Merineth 🇸🇪
Ok so all the way back
try
{
decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
catch (AlexDivideByZeroException)
{
Console.WriteLine($"Exception: Divide by zero: {number1}/{}");
}
try
{
decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
catch (AlexDivideByZeroException)
{
Console.WriteLine($"Exception: Divide by zero: {number1}/{}");
}
How do i access number1 and number2? Because they're still undefined out here
Angius
Angius3w ago
try
{
decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
- catch (AlexDivideByZeroException)
+ catch (AlexDivideByZeroException ex)
{
Console.WriteLine($"Exception: Divide by zero: {number1}/{}");
}
try
{
decimal output = calculationHandler.Run(top);
Console.WriteLine("= {0}", output);
}
- catch (AlexDivideByZeroException)
+ catch (AlexDivideByZeroException ex)
{
Console.WriteLine($"Exception: Divide by zero: {number1}/{}");
}
That ex will be the instance of your exception And it has those two properties you defined
Merineth 🇸🇪
Like so?
Angius
Angius3w ago
ex.number1
Merineth 🇸🇪
ooh OOOH
Angius
Angius3w ago
ex.number2
Merineth 🇸🇪
Okay it's getting way more vividly clear hahah C# is tricky :catHeyHello:
Angius
Angius3w ago
It does make sense in the end, though
Merineth 🇸🇪
Yeah just to reiterate what i just did ... I created an Exception called AlexDivideByZeroException which is a subclass of Exception. In the exception we defined 2 fields (i think it's called fields or attributes) We then made a constructor which should hold 2 numbers. We throw a new exception with became an instance?
Angius
Angius3w ago
Two properties, not fields, and certainly not attributes And you did throw a new instance of this exception It did not magically become an instance when throwing
Merineth 🇸🇪
right I think i'm getting the hang of it luckily i have to create two more So i can get some more practice 💀
Merineth 🇸🇪
So now i'm trying to solve this however 4/3 and A + B result in indexoutofrangeexception But they should be treated differently Exception: Invalid Operation 4 / 3 Exception: Invalid token: A A + B Exception: Invalid token: & 5 & 6
Merineth 🇸🇪
time for a break c: thanks for the help guys 🫶 time to be suicidal
Want results from more Discord servers?
Add your server