I would like to create my own custom Exception (for my own practice), I have Man class and i would like to check the name (so its not empty, null and only English chars.
I'm not sure if I'm doing this right,
1.do i need to write the code that handles with the error (if occures) in the Custom Exception class? or in the Man's setter?
2. Where should i use the "throw new Exception" for best practice?
3. any comments\improvements about my code would be welcome.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace prog
{
class Program
{
static void Main(string[] args)
{
try
{
Man p = new Man("Dan");
}
catch (Exception e)
{
throw new NameNotValidException(e.Message);
}
}
}
class Man
{
private string name;
public string Name
{
get { return name; }
set
{
if (name == "" || name == null)
{
throw new NameNotValidException("error");
}
name = value;
}
}
public Man(string name)
{
this.name = name;
}
}
class NameNotValidException : Exception
{
public NameNotValidException()
{
Console.WriteLine("Please Write a valid name!");
}
public NameNotValidException(string message)
: base(message)
{
}
public NameNotValidException(string message, Exception inner)
: base(message, inner)
{
}
}
Thanks!
In this case it is more appropriate to throw ArgumentNullException instead. Which exception you end up using (your own or ArgumentNullException) does not matter and does not change the structure of the code below OR how you should handle an Exception.
You want to check value, not name in the setter.
Handle the exception at the calling code. If the calling code is not designed to handle the Exception then do not catch that Exception OR rethrow using throw to preserve the stack trace.
Throw the exception at the location where the code fails due to... (invalid value in this case)
Be careful with your getter/setter code, you were checking the wrong values and also bypassing the setter in the constructor in which case it would never throw an Exception to begin with.
Your Man class.
public class Man {
public Man(string name)
{
// notice capital N for Name so it is set on the property, not the field
// this will execute the setter for the Name property
this.Name = name;
}
public Man(){} // optional, but do not include the parameterized constructor you had as it sets the private fields directly OR include additional validation
private string name;
public string Name
{
get { return name; }
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentNullException("Name cannot be null or empty");
name = value;
}
}
}
Calling code which handles the exception.
try
{
// use parameterized constructor
Man p = new Man("Dan");
// or use an initializer
Man p = new Man{Name = "Dan"};
// the above initializer is actually short for
Man p = new Man();
p.Name = "Dan";
}
catch (ArgumentException e)
{
Console.WriteLine("Error occurred!! Do something...");
}
If you want to create a custom exception just extend any of the exception classes, e.g.:
class MyCustomException : System.Exception
{}
and the you can do throw new MyCustomException();
When you throw an exception you're saying "Hey, something went wrong!", so the caller can then do something about that. The exception's responsibility is to say what exactly went wrong, not how to handle it. So you should remove the Console.WriteLine("Please Write a valid name!"); from the exception. Instead, put that in the code that is actually expecting that error - i.e. your Main method.
static void Main(string[] args)
{
try
{
Man p = new Man("Dan");
}
catch (NameNotValidException e)
{
Console.WriteLine("Please Write a valid name! " + e.Message);
}
Also note that I'm using NameNotValidException in the catch block, not Exception. As a general rule you should be as specific as possible in handling errors - which is why we create custom exceptions in the first place =). For example, let's say you add an Age property, which throws an AgeNotValidException. If you catch Exception e, you'll say "Please Write a valid name!" for every error, including invalid ages. By treating every exception type separately, you can handle each error differently.
About your "throw new Exception" question, you're doing it correctly: You should throw exceptions when you are unable to do something - in this case, you are unable to set the user's name because the given name is invalid. However, you should also try and be more specific with your error messages, to make errors easier to recover from: In your case, you could change it to something along the lines of throw new NameNotValidException("Name can't be empty");, so you can tell the user not only that the name is invalid, but also exactly why.
if you want to change the message only you could use this :
throw new Exception("File check failed!");
As you need to check several types of invalid input (not empty, null and only English chars), my advice is to create the custom exception with a property for invalid input type. The example is below:
class InvalidInputCustomException : Exception
{
public string InputExceptionType { get; set; }
public InvalidInputCustomException(string inputExceptionType)
{
InputExceptionType = inputExceptionType;
}
}
Then you’ll need to create your class Man in which set accessor the input (in this code keyword value) will be checked and code lines - throw new InvalidInputCustomException .. - with corresponding input exception type in this custom exception constructor will be included. This class example is below:
class Man
{
private string _name;
public Man(string name)
{
this.Name = name;
}
public string Name
{
get { return _name; }
set
{
if (value == null)
{
throw new InvalidInputCustomException("null is not valid for input.");
}
else if (value == string.Empty)
{
throw new InvalidInputCustomException("empty is not valid for input.");
}
else
{
foreach (char ch in value)
{
if (!(ch >= 'A' && ch <= 'Z') && !(ch >= 'a' && ch <= 'z') &&
!(ch >= '0' && ch <= '9'))
{
throw new InvalidInputCustomException($"non English character {ch} is " +
$"not valid for input."); ;
}
}
}
_name = value;
}
}
}
The thrown exception must be caught in the place where to initialized Man class object its property Name is attempted to set (as for example:
p.Name = inputString
or through this object constructor as in the code example below).
The example of the Console application code is below:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter name and press key Enter:");
string inputString = Console.ReadLine();
try
{
Man p = new Man(inputString);
Console.WriteLine($"Entered name - {p.Name} - is valid.");
}
catch (InvalidInputCustomException ex)
{
Console.WriteLine($"Invalid input type - {ex.InputExceptionType}. Please enter valid name.");
}
catch (Exception ex)
{
Console.WriteLine("Unhandled exception " + ex.Message);
}
Console.WriteLine("Press any key to finish the program.");
Console.ReadLine();
}
}
The code example is more for custom exceptions understanding purposes. In real applications, you need to avoid exceptions throwing in situations related to user information entering - in this case, data validation tools must be used. During custom exception creation in a real application must be provided at least a parameterless constructor and a best practice is to add three additional constructors: with a string, with a string and an exception, for serialization.
Related
I am currently practicing creating my Exception class. The idea of this code is for the user to enter a password. In case its code is less than 5 characters, the program will throw an exception. I want that my program throw one exception with text("Password is too small") and the object of my Exception class use ToString method(where will write " Password Length Exception").What confuses me is why I get the message Unhandled exception.Password Length exception. Cannot print exception string because Exception.ToString () failed. You can see this in the photo
Here is my code.
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
Console.WriteLine(message);
}
public override string ToString()
{
throw new My_Exception(" Password Length exception ");
}
}
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter your password");
string Password = Console.ReadLine();
if (Password.Length < 5)
{
throw new My_Exception(" Password is too small ");
}
}
catch(My_Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
Remove the override .ToString().
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
Console.WriteLine(message);
}
}
The message will be shown by the base Exception.ToString(). You shouldn't thow an exception from another exception.
And in truth, you shouldn't Console.WriteLine() from inside the constructor of an Exception. It is the try/catch block that should print in any way it wants the exception.
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
}
}
See running example at https://ideone.com/FchSGc
Don't throw an exception in the .ToString method. Return a string with information about what happened.
public override string ToString()
{
return " Password Length exception ";
}
Or simply create a proper exception
public class PasswordToSmallException : Exception
{
public PasswordToSmallException()
: base("Password should be at least 5 characters")
{}
}
And then you just
catch(Exception ex)
{
Console.WriteLine(ex);
}
Problem : cannot print exception string because exception.tostring() failed
Solution : I think it is a problem with the computer. I had this message also. I just restart the computer and it work.
Hey everybody I am just getting into C# and was going over exception handling. I am trying to find a way to trigger my custom exception without actually throwing it. It seems clunky to write throw new "custom exception" every time I want to error handle. With the throw line commented out my exception never gets triggered and I know that is because I am originally setting the object to null but can't find a way around this.
public class Person
{
public Person(String name)
{
Name = name;
}
public String Name { get; set; }
}
public class PersonException : Exception
{
public PersonException() : base() {}
}
public class Program
{
static void Main(string[] args)
{
Person p = null;
try
{
p = new Person("kim");
//throw new PersonException();
}
catch (PersonException z) when(p.Name == "kim")
{
Console.WriteLine(z.Message);
}
}
}
}
I don't think you fully understand the concept of exceptions (or your description does not make sense).
Your code will only ever enter the later part of the code below once an exception has occurred. You are not throwing an exception and likewise your code will not result in an exception. Seeing as no exception is occurring and you aren't manually throwing an exception I see no reason why it should ever enter the catch statement. The whole idea is to catch the error, which occasionally you might have to throw.
try {
// your code here
}
catch (Exception ex) {
// here we catch a generic exception
}
...even this wouldn't activate your catch clause because attempting to cast an invalid string to an int would throw an error different to your custom PersonException.
public class Person
{
public Person(String name)
{
Name = name;
}
public String Name { get; set; }
public int Age { get; set; }
}
try
{
p = new Person("kim");
p.Age = Convert.ToInt32("NOT AN INT");
}
catch (PersonException z) when(p.Name == "kim")
{
Console.WriteLine(z.Message);
}
Exceptions are for exceptional circumstances. You just need an if or switch block to check if the person's name is "kim".
All of the things already said by others apply and are good advice and I won't repeat them, but I think that what you're trying to do is better expressed as:
public class Program
{
static void Main(string[] args)
{
Person p = null;
try
{
p = new Person("kim");
if(p.Name == "kim")
{
throw new PersonException();
}
}
catch (PersonException z)
{
Console.WriteLine(z.Message);
}
}
}
...So you only throw the exception when you have the error situation, rather than only catch it in certain situations.
I am trying to find the cleanest solution for returning value or error message from function / method in c#.
For now I have tried:
public float ValidateValue (float value)
{
if (value == VALID_VALUE)
{
return value;
}
else
{
throw new ArgumentException("Invalid value", "value");
}
}
This solution seems to be good enough but in Clean Code Cheap Sheet I have found:
Using Exceptions for Control Flow – Don't do this
Using exceptions for control flow:
has bad performance, is hard to understand and results in very hard
handling of real exceptional cases.
What will you do in the case of invalid input?
If you are writing code at the UI level that is taking the input from the user then it makes most sense to do something like:
private bool IsValid(float value)
{
return value == VALID_VALUE; // replace with real check.
}
Then in the calling code you would have:
public void ReactToInput()
{
float value = HoweverYouGetTheFloatFromTheUser();
if(!IsValid)
{
//Code to display error message.
}
else
{
//Code to do something useful.
//
//Code to display result.
}
}
Because your job at this level is "take what the user gave me, return what they want as best I can" and at this level its best to have the possibility of the user doing something incorrect front and centre.
If you are writing code for other code to make use of, then it makes most sense to do something like:
private void CheckValid(float valid)
{
if(value != VALID_VALUE) // replace with real check.
throw new ArgumentException();
}
Then in the calling code you would have:
public float DoWork(float value)
{
CheckValid(value)
//Code to do something useful.
//
//Code to return result.
}
Here your job is to do what the method's task is cleanly and return a meaninful result (or void if there isn't one). If you can't do that job, because the input you were given is nonsense (or for any other reason) then you need to stop as soon as you can and deal with that problem. You could do this by returning an error/success code every time and having calling code checking it every time, but while this approach does indeed have some advantages, exceptions let us:
Write with a focus on the correct behaviour.
Pass up exceptions.
For an example of 1, compare:
private bool WithExceptions()
{
return A() > B() && C() > D();
}
private bool WithExplicitChecks(out bool result)
{
result = false;
int a;
int b;
if(!A(out a))
return false;
if(!B(out b))
return false;
if(a <= b)
return true;
int c;
int d;
if(!C(out c))
return false;
if(!D(out d))
return false;
result = c > d;
return true;
}
For an example of 2, consider:
private void A()
{
if(_someField == null)
throw new InvalidOperationException("field not ready");
_someField.DoSomething();
}
private void B()
{
A();
}
private void C()
{
B();
}
private string D()
{
try
{
C();
}
catch(InvalidOperationException)
{
Console.Error.WriteLine("Was not ready");
}
}
Obviously a real case would have B() and C() do more, but we can see here that only A() has to worry about raising exceptions and only D() about dealing with them, B() and C() can both just concentrate on the main concern.*
The two approaches can be mixed. Consider:
private static string CheckValid(string path)
{
if(path.Length == 0)
return "You cannot enter an empty file path";
switch(path[path.Length - 1])
{
case '\\':
case '/':
return "You cannot enter a directory path";
}
return null;
}
public static void Main(string[] args)
{
Console.WriteLine("Enter a file path");
var path = Console.ReadLine().Trim();
var validationError = CheckValid(path);
if(validationError != null)
Console.Error.WriteLine(validationError);
else
{
try
{
using(var reader = new StreamReader(path))
Console.WriteLine(reader.ReadToEnd());
}
catch(FileNotFoundException)
{
Console.Error.WriteLine("File not found");
}
catch(UnauthorizedAccessException)
{
Console.Error.WriteLine("Access denied");
}
catch(IOException ioe)
{
Console.Error.WriteLine(string.Format("I/O Exception: {0}", ioe.Message));
}
}
Console.Read();
}
This simple program takes a file path from the user, and opens the relevant file and outputs the contents as text. It takes both approaches to error-handling.
Because we can easily check for invalid input that is empty, or which ends with / or \, that is done with simple control-flow and we present an error message instead of doing something.
Other issues we can only know about by trying to open the file and failing, so in those cases we handle the exceptions. I combine both explicit checks for two types of problem along with one for a general class of problems, and act accordingly.
There is a third type of exception handling here; if an exception happens that I don't expect at all, the program fails with a exception message being dumped for debugging purposes. This is the case anywhere you don't catch all exceptions, but a very useful one; because I don't have a blanket catch or catch(Exception) I don't confuse exceptions I'm expecting to deal with (go me for handling them!) with exceptions that are there because I made a mistake in not realising they could happen (boo me! now I have to fix it).
This is a simple program that takes a file path from the user, and outputs the contents of the file. Note that it combines both approaches:
*Do though always consider that something started in a method may not be finished if an exception busts through it.
If you want to validate some input value, I would expect a bool to be returned indicating 'valid' or 'invalid', or no return value and an exception thrown when the value is invalid.
So I would suggest to use this:
public bool ValidateValue(float value)
{
return value == VALID_VALUE;
}
Or this:
public void ValidateValue(float value)
{
if (value != VALID_VALUE)
{
throw new ArgumentException("Invalid value", "value");
}
}
So throwing an exception is not a problem, especially when there are multiple reasons to reject, and you want to distinguish the various reasons. Otherwise, just use a bool, like int.TryParse does for example.
A tuple may be useful to solve that issue:
public Tuple<float,string> ValidateValue (float value)
if (value == VALID_VALUE)
{
return new Tuple<bool, string>(value,string.Empty);
}
else
{
return new Tuple<bool, string>(false,"Invalid value");
}
When calling a function, check if the error string is empty first:
var validation = ValidateValue(myFloatValue);
if (validation.Item2 != string.Empty)
{
// report error
}
else
{
// No error core here validation.Item1 is your result
}
One idea could be to have some generic model. You may have some model roughly like:
public class MyReturnModel
{
public bool Success { get; set; }
public string ErrorOrSuccessMessage { get; set; }
public dynamic AnyModelToReturn { get; set; }
}
Now let's apply this on your provided case:
public MyReturnModel ValidateValue(float value)
{
//function logic here
bool result = value == VALID_VALUE;
string msg = result ? "valud is valid" : "value is invalid";
return new MyReturnModel { Success = result, ErrorOrSuccessMessage = msg }
}
I'm writing a service which's methods must not throw exceptions but should return a generic Message-object which contains the actual result of the method call and exceptions if any have occured. This Message class looks like this:
public class Message<T>
{
private List<Exception> exceptions = new List<Exception>();
public T Result { get; set; }
public void AddException(Exception x)
{
this.exceptions.Add(x);
}
public bool HasExceptions
{
get
{
return this.exceptions.Count > 0;
}
}
public IEnumerable<Exception> Exceptions
{
get
{
foreach (var exception in this.exceptions)
yield return exception;
}
}
}
Usually the implementation of a service method then looks like this:
public Message<int> MyServiceMethod()
{
var msg = new Message<int>();
try
{
// do something useful here
msg.Result = 42;
}
catch (Exception x)
{
msg.AddException(x);
}
return msg;
}
The caller can then handle exceptions if necessary.
var msg = service.MyServiceMethod();
if (msg.HasExceptions)
{
// Handle exceptions here
}
Now I have a service method with an argument which must be in a certain range. Since it feels natural for me to respond with an ArgumentOutOfRangeException if the argument is out of range, I implemented it like this:
public Message<int> MyOtherServiceMethod(int arg)
{
var msg = new Message<int>();
if (arg < 1)
{
msg.AddException(new ArgumentOutOfRangeException("arg", "Argument must be greater than 0"));
return msg;
}
// ...
return msg;
}
Basically this works. The only thing I'm missing is the stack trace of the exception. This is not a problem since I don't need that in my scenario. But it made me wonder, are there any other "side effects" which might cause trouble when the exception is used but not thrown?
You should use some construction that takes message and exception as arguments:
try
{
// do something useful here
}
catch (Exception x)
{
throw YourPreferredException(some_message, x);
}
This will make x available as yourPreferredException.InnerException property.
Also, I don't think it's a good design choice to have a method returning Message and running the try/catch block inside it (should be the other way around).
I would say that's not really the intended use of exceptions in C#. If you want a custom message then you just use the Exception constructor that takes a message and another instance of type Exception, this will give you a new exception with your custom message plus the original exception set as the instances InnerException property. You're just reinventing the wheel here with some custom 'message' class. If all you want to do is return a message (like you don't want to throw) then you should be taking the exceptions Message property and assigning it to some string or returning that string directly.
Here are a couple more idiomatic examples for handling your error;
Message ret = new Message();
try
{}
catch (Exception e)
{
ret.ErrorPropertyOfTypeString = e.Message;
}
return ret;
Message ret = new Message();
try
{}
catch (Exception e)
{
throw new Exception("My custom message here", e);
}
return ret;
Whatever you're doing, one of the two patterns above should probably used instead.
I have methods that look like this:
public IDictionary<string, string> Delete(Account account)
{
try { _accountRepository.Delete(account); }
catch { _errors.Add("", "Error when deleting account"); }
return _errors;
}
public IDictionary<string, string> ValidateNoDuplicate(Account ac)
{
var accounts = GetAccounts(ac.PartitionKey);
if (accounts.Any(b => b.Title.Equals(ac.Title) &&
!b.RowKey.Equals(ac.RowKey)))
_errors.Add("Account.Title", "Duplicate");
return _errors;
}
I would like to change this method so that it returns a bool and so it throws an exception if there is an error instead of:
_errors.Add("", "Error when deleting account");
Can someone explain to me how I can throw an exception and pass a message containing a key and a value. In this case the key would be "" and the value would be "Error when deleting account".
Also in the method that calls this. How would I catch the exception?
Would it be necessary for me to make my own class and somehow throw an exception based on this class?
Create your own exception class, that can hold the data that you need:
public class AccountException : ApplicationException {
public Dictionary<string, string> Errors { get; set; };
public AccountException(Exception ex) : base(ex) {
Errors = new Dictionary<string, string>();
}
public AccountException() : this(null) {}
}
In your methods you can throw the exception. Don't return an error status also, that is handled by the exception.
Don't throw away the exception that you get in the method, include that as InnerException, so that it can be used for debugging.
public void Delete(Account account) {
try {
_accountRepository.Delete(account);
} catch(Exception ex) {
AccountException a = new AccountException(ex);
a.Errors.Add("", "Error when deleting account");
throw a;
}
}
public void ValidateNoDuplicate(Account ac) {
var accounts = GetAccounts(ac.PartitionKey);
if (accounts.Any(b => b.Title.Equals(ac.Title) &&
!b.RowKey.Equals(ac.RowKey))) {
AccountException a = new AccountException();
a.Errors.Add("Account.Title", "Duplicate");
throw a;
}
}
When calling the methods, you catch your exception type:
try {
Delete(account);
} catch(AccountException ex) {
// Handle the exception here.
// The ex.Errors property contains the string pairs.
// The ex.InnerException contains the actual exception
}
The Exception class has a Data property that is a dictionary of key/value pairs.
IDictionary<string, string> errors;
...
if (errors.Count > 0)
{
Exception ex = ... construct exception of the appropriate type
foreach(string key in _errors.Keys)
{
ex.Data.Add(key, _errors[key]);
}
throw ex;
}
Note that it's generally considered to be good practice to use Exceptions that are Serializable, so that the objects you put into the Data dictionary should also be serializable. In your example, you're just putting in strings, so you'll be fine.
Would it be necessary for me to make my own class and somehow throw an exception based on this class?
It's certainly not necessary to create your own custom Exception class, and may not be desirable. The MSDN design guidelines for Exceptions gives guidelines on choosing which Exception type to throw.
In general, you should prefer to use one of the existing Exception types unless you have an error condition that can be programatically handled in a different way from existing Exception types.
Create your own Exception and then throwing it.
public class RepositoryException : Exception
{
public RepositoryException() : base()
{
}
public RepositoryException(string key, string value) : base()
{
base.Data.Add(key, value);
}
public RepositoryException(string message) : base(message)
{
}
public RepositoryException(string message, Exception innerException) : base(message, innerException)
{
}
}
public Boolean Delete(Account account)
{
try
{
_accountRepository.Delete(account);
return true;
}
catch (Exception ex)
{
throw new RepositoryException("", "Error when deleting account");
// throw new RepositoryException("Error when deleting account", ex);
// OR just
// throw new RepositoryException("Error when deleting account");
}
}
You could throw your own exceptions instead of
_errors.Add("", "Error when deleting account");
So every _errors.Add(..) will be replaced with something like
throw new MyAppException(key, value);
How to create your own exception class was explained above. So you supply your exception object with key and value.
You should know which exception type you're going to catch
try {
Delete(account);
} catch(NullPointerException ex) {
throw new MyAppException(key, value);
}
And now in your caller-methods(outer-methods) you can catch only your exceptions.
try {
_accountRepository.Delete(account);
} catch(MyAppException ex) {
//exception handle logic
}