如果我从基类继承,并想将继承类的构造函数传递给基类的构造函数,我该怎么做?

例如,如果我从Exception类继承,我希望执行以下操作:

class MyExceptionClass : Exception
{
     public MyExceptionClass(string message, string extraInfo)
     {
         //This is where it's all falling apart
         base(message);
     }
}

基本上,我希望能够将字符串消息传递给基础Exception类。


当前回答

的确,使用base(something)调用基类构造函数,但在重载的情况下,使用this关键字

public ClassName() : this(par1,par2)
{
// do not call the constructor it is called in the this.
// the base key- word is used to call a inherited constructor   
} 

// Hint used overload as often as needed do not write the same code 2 or more times

其他回答

将构造函数修改为以下值,以便正确调用基类构造函数:

public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message, string extrainfo) : base(message)
    {
        //other stuff here
    }
}

请注意,构造函数不是可以在方法中随时调用的。这就是在构造函数主体中调用时出错的原因。

您还可以使用构造函数中的参数进行条件检查,这允许一些灵活性。

public MyClass(object myObject=null): base(myObject ?? new myOtherObject())
{
}

or

public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
{
}

根据这里列出的一些其他答案,您可以将参数传递给基类构造函数。建议在继承类的构造函数的开头调用基类构造函数。

public class MyException : Exception
{
    public MyException(string message, string extraInfo) : base(message)
    {
    }
}

我注意到,在您的示例中,您从未使用过extraInfo参数,因此我假设您可能希望将extraInfo字符串参数连接到异常的Message属性(似乎在接受的答案和问题中的代码中忽略了这一点)。

这只需调用基类构造函数,然后使用额外的信息更新Message属性即可实现。

public class MyException: Exception
{
    public MyException(string message, string extraInfo) : base($"{message} Extra info: {extraInfo}")
    {
    }
}

例如,使用要从中派生的基类:

public abstract class BaseClass
{
    protected BaseClass(int a, int b, int c)
    {
    }
}

要执行的非编译伪代码:

public class DerivedClass : BaseClass
{
    private readonly object fatData;
    
    public DerivedClass(int m)
    {
        var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
        base(fd.A, fd.B, fd.C); // base-constructor call
        this.fatData = fd;
    }
}

2020版本(见下文,了解更严格的解决方案)

使用更新的C#特性,即out-var,您可以摆脱公共静态工厂方法。

我刚刚(偶然)发现,在base内部调用的方法的out var参数-“call”流到构造函数主体。(可能是C#的怪癖,请参阅2023版本的C#1.0兼容解决方案)

使用一个静态私有帮助器方法,它可以向外部生成所有必需的基本参数(如果需要,还可以添加其他数据),这只是一个公共的普通构造函数:

public class DerivedClass : BaseClass
{
    private readonly object fatData;
    
    public DerivedClass(int m)
        : base(PrepareBaseParameters(m, out var b, out var c, out var fatData), b, c)
    {
        this.fatData = fatData;
        Console.WriteLine(new { b, c, fatData }.ToString());
    }

    private static int PrepareBaseParameters(int m, out int b, out int c, out object fatData)
    {
        var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
        (b, c, fatData) = (fd.B, fd.C, fd); // Tuples not required but nice to use
        return fd.A;
    }
}

2023更新

您只需要一个额外的私有构造函数和一个附带的私有静态工厂方法,该方法使用与公共构造函数相同的输入为新的私有构造函数准备数据:

public class DerivedClass : BaseClass
{
    private readonly FatData fatData;

    public DerivedClass(int m)
        : this(PrepareBaseParameters(m))
    {
        Console.WriteLine(this.fatData.ToString());
    }

    private DerivedClass(FatData fd)
        : base(fd.A, fd.B, fd.C)
    {
        this.fatData = fd;
    }

    private static FatData PrepareBaseParameters(int m)
    {
        // might be any (non-async) code which e.x. calls factory methods 
        var fd = new FatData(A: 1 * m, B: 2 * m, C: 3 * m);
        return fd;
    }

    private readonly record struct FatData(int A, int B, int C);
}

不需要特殊的C#版本,C#10记录结构只是为了简短,也可以与任何C#1.0类一起使用。

这个版本似乎稍长,但它更容易阅读和理解。

的确,使用base(something)调用基类构造函数,但在重载的情况下,使用this关键字

public ClassName() : this(par1,par2)
{
// do not call the constructor it is called in the this.
// the base key- word is used to call a inherited constructor   
} 

// Hint used overload as often as needed do not write the same code 2 or more times