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

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

例如,

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

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

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

答案

将您的构造函数修改为以下代码,以便它正确调用基类的构造函数:

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

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

请注意,可以在对基本构造函数的调用中使用静态方法。

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

如果由于新的(派生的)类需要进行一些数据操作而需要立即调用基本构造函数,那么最好的解决方案是采用工厂方法。您需要做的是将派生的构造函数标记为私有,然后在您的类中创建一个静态方法来处理所有必要的工作,然后调用该构造函数并返回该对象。

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

确实可以使用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
public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message,
      Exception innerException): base(message, innerException)
    {
        //other stuff here
    }
}

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

来自框架设计准则和 FxCop 规则。

1. 自定义例外的名称应以例外结尾

class MyException : Exception

2. 例外应该是公开的

public class MyException : Exception

3. CA1032:异常应实现标准的构造函数。

  • 一个公共的无参数构造函数。
  • 一个带有一个字符串参数的公共构造函数。
  • 一个带有一个字符串和 Exception 的公共构造函数(因为它可以包装另一个 Exception)。
  • 如果类型不是密封的,则序列化构造函数将受到保护;如果类型是密封的,则序列化构造函数将为私有。基于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.
      }
    }

您还可以在构造函数中使用参数进行条件检查,从而具有一定的灵活性。

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

要么

public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
{
}
class Exception
{
     public Exception(string message)
     {
         [...]
     }
}

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

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

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 class MyException : Exception
{
    public MyException() { }
    public MyException(string msg) : base(msg) { }
    public MyException(string msg, Exception inner) : base(msg, inner) { }
}