如何用C#从派生类中的构造函数捕获异常?

如何用C#从派生类中的构造函数捕获异常?,c#,.net,exception-handling,constructor,C#,.net,Exception Handling,Constructor,我想知道如何从C#派生类中的构造函数捕获异常。例如: public class MyClassA { public MyClassA() { //Do the work if (failed) { throw new Exception("My exception"); } } } public class MyClassB : MyClassA { public MyCla

我想知道如何从C#派生类中的构造函数捕获异常。例如:

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?
    }
}
1) 解决方法:在派生的:

class MyClassB : MyClassA
{
    public static MyClassB Create()
    {
        try
        {
            return new MyClassB();
        }
        catch
        {
            // try to handle
        }
    }
}
2) 或者在基中创建一个类似的函数,而不是在构造函数中,而是在方法中:

3) 或者提供一个可覆盖的策略来处理失败状态:

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

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

class MyClassB : MyClassA
{
    protected override void OnFail()
    {
        // don't throw
    }
}   

我想我会这样处理

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?
        }

    }
}

甚至不要试图找出如何做到这一点。如果基类构造函数抛出异常,则表示基类处于错误状态。如果基类处于错误状态,则表示派生类处于错误状态。构造函数的要点是使对象进入可用状态。它失败了。出去

我用静态方法解决了同样的问题:

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");
        }
    }
}

我担心这是不可能的。可能只有我一个人,但我一直试图避免施工人员做“工作”。我认为这是一种非常不寻常的行为,可能会给不熟悉代码库的开发人员带来麻烦。与其他一些OOP语言不同,从C#构造函数抛出异常具有定义良好的行为。捕获它也有很好的定义,需要对新操作符进行try/catch操作。所以至少比你希望的位置高一层。在派生类中捕获它当然不起作用,这是一个没有地下室的纸牌屋。抛出异常非常昂贵。这是一个更好的选择approach@HasTaiar:这不是真的。即使在C++中。谢谢abatishchev,即使在你提供的链接中,这仍然是有争议的。。干杯:)我不同意。如果您的基类不能被构造,那么代码就有很大的问题。我将把建立对象内部状态的逻辑移到方法调用中,并将基本构造留给方法调用。这可以让你更好地控制你的代码,你可以把它倒过来。在这种情况下,基类构造得很好,但派生类抛出。这通常是一个一次性对象的问题,在这个对象中,基类希望被释放(因为它的构造函数工作),但不会是因为派生类中的构造函数失败。@Yaur:你在说什么?阅读代码:
MyClassB:MyClassA
。我的坏。将此错误理解为一个更有趣的问题:如何使用工厂方法从基类继承(您的选项#2)?+1表示#3。我有一个通用的基工厂类,它使用反射从一个名称实例化一个具体的类。通过重写派生的具体工厂类上的虚方法,我可以在基类出错时实现自定义错误处理。
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");
        }
    }
}