4

I was wondering how to catch an exception from a constructor in a derived class with C#. Something as such:

public class MyClassA
{
    public MyClassA()
    {
        //Do the work
        if (failed)
        {
            throw new Exception("My exception");
        }
    }
}

public class MyClassB : MyClassA
{
    public MyClassB()
    {
        //How to catch exception from a constructor in MyClassA?
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • I'm afraid that this isn't possible. – Daniel A. White Jun 23 '13 at 23:04
  • It may be just me, but I have always tried to avoid constructors doing "work". I think it is quite unusual behavior and could prove troublesome for developers who are not as knowledgeable with the codebase. – Lukazoid Jun 23 '13 at 23:06
  • 4
    Unlike some other OOP languages, throwing exceptions from a C# constructor has well defined behavior. Catching it is well defined too, it requires a try/catch around the *new* operator. So at least one level up from where you hope to put it. Catching it in the derived class won't work of course, that's a house of cards without a basement. – Hans Passant Jun 23 '13 at 23:21

4 Answers4

7

Do not even try to figure out how to do this. If the base class constructor is throwing an exception, it means the base class is in a bad state. If the base class is in a bad state, it means the derived class is in a bad state. The point of a constructor is to get an object into a useable state. It failed. Get out!

jason
  • 236,483
  • 35
  • 423
  • 525
  • You have it backwards. In this case the base class is constructed just fine, but the derived class throws. This is typically a problem with Disposable objects where the base class is expecting to be disposed (because its constructor worked) but it won't be because a constructor in a derived class failed. – Yaur Jun 23 '13 at 23:19
  • 1
    @Yaur: What are you talking about? Read the code: `MyClassB : MyClassA`. – jason Jun 23 '13 at 23:28
  • My bad. mistook this for a more interesting problem – Yaur Jun 24 '13 at 21:17
1

1) A workaround: create a factory method in the derived:

class MyClassB : MyClassA
{
    public static MyClassB Create()
    {
        try
        {
            return new MyClassB();
        }
        catch
        {
            // try to handle
        }
    }
}

2) or create a similar in the base and don't throw in the constructor but in the method instead:

class MyClassA
{
    public static MyClassA Create()
    {
        MyClassA x = new MyClassA();
        if (x.Failed)
            throw new Exception();
        return x;
    }
}

3) or provide an overridable strategy to handle failed state:

class MyClassA
{
    public MyClassA
    {
        if (failed)
            OnFail();
    }

    protected virtual void OnFail()
    {
         throw new Exception();
    }
}

class MyClassB : MyClassA
{
    protected override void OnFail()
    {
        // don't throw
    }
}   
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • How do you inherit from a base class with factory method (your option #2)? – svick Jun 23 '13 at 23:35
  • 1
    +1 for #3. I have a generic base factory class that uses reflection to instantiate a concrete class from a name. By overriding a virtual method on the derived concrete factory classes, I can implement custom error handling when something goes wrong in the base class. – Brandon Gano May 01 '15 at 00:07
1

i would handle it like this i think

public class MyClassA
{

    protected bool test;
    public MyClassA()
    {
        //Do the work
        if (true)
        {
            test = true;
            return;
        }
    }
}

public class MyClassB : MyClassA
{
    public MyClassB() 
    {
        if (base.test)
        {
            //How to catch exception from a constructor in MyClassA?
        }

    }
}
Fredou
  • 19,848
  • 10
  • 58
  • 113
  • throwing exceptions is very expensive. This is a better approach – Has AlTaiar Jun 23 '13 at 23:12
  • 1
    @HasTaiar: This is not true. Even in C++. [In C# exceptions are not expensive at all](http://stackoverflow.com/questions/891217/how-expensive-are-exceptions-in-c) – abatishchev Jun 23 '13 at 23:13
  • Thanks abatishchev, that 's still controversial even in the link u provided.. Cheers :) – Has AlTaiar Jun 23 '13 at 23:18
  • I would disagree. If your base class can't be constructed then something is majorly wrong with the code. I would move the logic to build up the internal state of an object to a method call and leave the base construction to just that. This gives you better control over your code. – tsells Jun 24 '13 at 05:12
1

I solve the same problem with static method:

public class PdfReaderExtended : PdfReader
{
    public PdfReaderExtended(string filename) : base(filename)
    {

    }

    public static PdfReaderExtended CreateInstance(string filename)
    {
        var name = Path.GetFileName(filename);
        try
        {
            return new PdfReaderExtended(filename);
        }
        catch (Exception ex)
        {
            throw new ClientException("Oops");
        }
    }
}
Botan
  • 43
  • 4