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

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

Например,

Если я наследую от класса Exception, я хочу сделать что-то подобное:

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

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

10 ответов

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

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

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

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

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

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

    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;
         }
    }
    
  4. Если вам нужно вызвать базовый конструктор, но не сразу, потому что ваш новый (производный) класс должен выполнить некоторую манипуляцию данными, лучшее решение-прибегнуть к заводскому методу. То, что вам нужно сделать, это пометить частный ваш производный конструктор, а затем сделать статический метод в вашем классе, который будет делать все необходимые вещи, а затем вызвать конструктор и вернуть объект.

    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);
        }
    }
    
  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. class Exception
    {
         public Exception(string message)
         {
             [...]
         }
    }
    
    class MyExceptionClass : Exception
    {
         public MyExceptionClass(string message, string extraInfo)
         : base(message)
         {
             [...]
         }
    }
    
  7. Из руководящих принципов проектирования рамок и правил FxCop.:

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

        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.
          }
        }  
    
  8. public class MyException : Exception
    {
        public MyException() { }
        public MyException(string msg) : base(msg) { }
        public MyException(string msg, Exception inner) : base(msg, inner) { }
    }
    
  9. Можно также выполнить условную проверку параметров в конструкторе, что обеспечивает некоторую гибкость.

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

    или

    public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
    {
    }
    
  10. Согласно некоторым другим ответам, перечисленным здесь, можно передать параметры в конструктор базового класса. Рекомендуется вызывать конструктор базового класса в начале конструктора для унаследованного класса.

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