Search code examples
c#objectcustom-exceptions

Custom Exception C#


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!


Solution

    1. 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.
    2. You want to check value, not name in the setter.
    3. 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.
    4. Throw the exception at the location where the code fails due to... (invalid value in this case)
    5. 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...");
    }