Вызов базового конструктора в С#

Если я наследую от базового класса и хочу передать что-то из конструктора унаследованного класса в конструктор базового класса, как это сделать?

Например,

Если я наследую класс Exception, я хочу сделать что-то вроде этого:

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

В основном, я хочу, чтобы передать строковое сообщение в базовый класс Exception.

Ответ 1

Измените свой конструктор следующим образом, чтобы он правильно вызвал конструктор базового класса:

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

Обратите внимание, что конструктор не является тем, что вы можете вызвать в любое время в рамках метода. Это причина, по которой вы получаете ошибки в своем вызове в теле конструктора.

Ответ 2

Обратите внимание, что вы можете использовать методы 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;
     }
}

Ответ 3

Если вам нужно вызвать базовый конструктор, но не сразу, потому что вашему новому (производному) классу необходимо выполнить некоторые манипуляции с данными, лучшим решением является обращение к методу factory. Что вам нужно сделать, это пометить частный производный конструктор, а затем создать в своем классе статический метод, который сделает все необходимое, а затем вызовет конструктор и вернет объект.

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

Ответ 4

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

Вы можете передать внутреннее исключение одному из конструкторов.

Ответ 5

Верно использовать 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

Ответ 6

Из Принципы проектирования каркаса и правила FxCop.:

1. Пользовательское исключение должно иметь имя, которое заканчивается Exception

    class MyException : Exception

2. Исключение должно быть общедоступным

    public class MyException : Exception

3. CA1032: Исключение должно реализовывать стандартные конструкторы.

  • Открытый конструктор без параметров.
  • Открытый конструктор с одним строковым аргументом.
  • Открытый конструктор с одной строкой и 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.
      }
    }  

Ответ 7

Вы также можете выполнить условную проверку с параметрами в конструкторе, что дает некоторую гибкость.

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

или

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

Ответ 8

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

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

Ответ 9

public class MyException : Exception
{
    public MyException() { }
    public MyException(string msg) : base(msg) { }
    public MyException(string msg, Exception inner) : base(msg, inner) { }
}

Ответ 10

В соответствии с некоторыми другими приведенными здесь ответами вы можете передавать параметры в конструктор базового класса. Рекомендуется назначить конструктор базового класса в начале конструктора для вашего унаследованного класса.

public class MyException : Exception
{
    public MyException(string message, string extraInfo) : base(message)
    {
        this.Message = $"{message} Extra info: {extraInfo}";
        // You can omit the 'this.' portion above...
    }
}

Я отмечаю, что в вашем примере вы никогда не использовали параметр extraInfo, поэтому я предположил, что вы захотите объединить строковый параметр extraInfo в свойство Message вашего исключения (кажется, что это игнорируется в принятом ответе и в коде в вашем вопросе).

Это просто достигается путем вызова конструктора базового класса и последующего обновления свойства Message с дополнительной информацией.

В качестве альтернативы, поскольку свойство Message наследуется от базового класса, вам даже не нужно явно вызывать конструктор базового класса. Вы можете просто обновить свойство Message непосредственно от конструктора вашего унаследованного класса, например:

public class MyException : Exception
{
    public MyException(string message, string extraInfo)
    {
        this.Message = $"{message} Extra info: {extraInfo}";
        // You can omit the 'this.' portion above...
    }
}