在C#中调用基础构造函数

时间:2008-08-15 07:39:23

标签: c# inheritance constructor

如果我从基类继承并希望将继承类的构造函数中的某些东西传递给基类的构造函数,我该怎么做?

例如,

如果我从Exception类继承,我想做这样的事情:

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

基本上我想要的是能够将字符串消息传递给基本的Exception类。

13 个答案:

答案 0 :(得分:1646)

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

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

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

答案 1 :(得分:464)

请注意,您可以在对基础构造函数的调用中使用 static 方法。

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

     private static string ModifyMessage(string message, string extraInfo)
     {
         Trace.WriteLine("message was " + message);
         return message.ToLowerInvariant() + Environment.NewLine + extraInfo;
     }
}

答案 2 :(得分:88)

如果你需要调用基础构造函数但不能立即调用,因为你的新(派生)类需要进行一些数据操作,最好的解决方案是采用工厂方法。你需要做的是标记私有你的派生构造函数,然后在你的类中创建一个静态方法,它将执行所有必要的东西,然后调用构造函数并返回对象。

public class MyClass : BaseClass
{
    private MyClass(string someString) : base(someString)
    {
        //your code goes in here
    }

    public static MyClass FactoryMethod(string someString)
    {
        //whatever you want to do with your string before passing it in
        return new MyClass(someString);
    }
}

答案 3 :(得分:28)

确实使用base(某事物)来调用基类构造函数,但是在重载的情况下使用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

答案 4 :(得分:25)

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

您可以将内部异常传递给其中一个构造函数。

答案 5 :(得分:18)

来自Framework Design Guidelines和FxCop规则。

<强> 1。自定义例外的名称应以“例外”

结尾
    class MyException : Exception

<强> 2。例外应该是公开的

    public class MyException : Exception

第3。 CA1032: Exception should implements standard constructors.

  • 公共无参数构造函数。
  • 具有一个字符串参数的公共构造函数。
  • 具有一个字符串和Exception的公共构造函数(因为它可以包装另一个Exception)。
  • 如果类型未密封,则序列化构造函数受保护;如果类型已密封,则为private。 基于MSDN

    [Serializable()]
    public class MyException : Exception
    {
      public MyException()
      {
         // Add any type-specific logic, and supply the default message.
      }
    
      public MyException(string message): base(message) 
      {
         // Add any type-specific logic.
      }
      public MyException(string message, Exception innerException): 
         base (message, innerException)
      {
         // Add any type-specific logic for inner exceptions.
      }
      protected MyException(SerializationInfo info, 
         StreamingContext context) : base(info, context)
      {
         // Implement type-specific serialization constructor logic.
      }
    }  
    

    [Serializable()]
    public sealed class MyException : Exception
    {
      public MyException()
      {
         // Add any type-specific logic, and supply the default message.
      }

      public MyException(string message): base(message) 
      {
         // Add any type-specific logic.
      }
      public MyException(string message, Exception innerException): 
         base (message, innerException)
      {
         // Add any type-specific logic for inner exceptions.
      }
      private MyException(SerializationInfo info, 
         StreamingContext context) : base(info, context)
      {
         // Implement type-specific serialization constructor logic.
      }
    }  

答案 6 :(得分:13)

您还可以在构造函数中使用参数进行条件检查,这样可以提供一些灵活性。

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

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

答案 7 :(得分:7)

class Exception
{
     public Exception(string message)
     {
         [...]
     }
}

class MyExceptionClass : Exception
{
     public MyExceptionClass(string message, string extraInfo)
     : base(message)
     {
         [...]
     }
}

答案 8 :(得分:7)

$(function() {
  $('#container').highcharts({
    title: { text: null },
    subtitle: { text: null },
    legend: { enabled: false },
    xAxis: { 
      type: 'datetime',
      title: { text: null }
    },
    yAxis: [{  
        top: 10,
      height: 60,
      offset: 0,
      title: { text: 'Plot 1'}
    },{
        top: 80,
      height: 60,
      offset: 0,
      title: { text: 'Plot 2'}
    }]
  });   
 chart = $('#container').highcharts();
    chart.addSeries({ 
    yAxis: 0,
    type: 'scatter',
    marker: {
        enabled: true,
      symbol: 'triangle'
    },
    data: [[1356977700000,1], [1359656100000,1], [1364753700000,1]] 
  });
  chart.addSeries({ 
    yAxis: 1,
    type: 'columnrange',
    data: [[1356977700000, 1359656100000], [1362075300000, 1364753700000]]  
  });   
});

答案 9 :(得分:6)

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

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

答案 10 :(得分:3)

使用更新的C#功能(即out var),您可以摆脱静态的工厂方法。 我只是偶然发现了inse base-“ call”方法的var参数流到构造函数主体。

示例,使用您要派生的该基类:

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

以及使用静态私有帮助器方法的解决方案,该方法会生成所有必需的基本参数(如果需要,还会添加其他数据),而无需使用静态工厂方法,而只是外部的普通构造函数:

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

答案 11 :(得分:3)

public class Car
{
     public Car(string model)
     {
        Console.WriteLine(model);
     }
}

public class Mercedes : Car
{
     public Mercedes(string model): base(model)
     {

     }
}

用法:

Mercedes mercedes = new Mercedes("CLA Shooting Brake");

输出:CLA刹车片

答案 12 :(得分:1)

在构造函数之后添加 : base("string or something"),而不是在其主体内部。

public class MyException : System.Exception {
    public MyException(string msg) : base(msg) {
        // code here
    }
}