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

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

например,

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

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

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

11 ответов


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

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

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


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

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

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

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

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


Это правда использовать 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

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

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

    class MyException : Exception

2. Исключение должно быть public

    public class MyException : Exception

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

  • открытый конструктор без параметров.
  • публичный конструктор с одним строковый аргумент.
  • открытый конструктор с одной строкой и исключением (поскольку он может обернуть другое исключение).
  • конструктор сериализации защищен, если тип не запечатан, и является закрытым, если тип запечатан. На основе 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() { }
    public MyException(string msg) : base(msg) { }
    public MyException(string msg, Exception inner) : base(msg, inner) { }
}

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

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 параметр string для 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...
    }
}

используя base, вы можете вызвать конструктор базового класса

class BaseClass
    {

    public BaseClass(int val)
    {
        Console.WriteLine($"{nameof(BaseClass) } constructor");
    }
   }

    class DerivedClass : BaseClass
    {
    public DerivedClass() : base(10)
    {
        Console.WriteLine($"{nameof(DerivedClass) } constructor");
    }
    }
    class Program
    {
        static void Main(string[] args)
        {
        BaseClass baseClass = new DerivedClass();
          Console.ReadLine();

        }
    }