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


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

例如,

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

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

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


1156
2017-08-15 07:39


起源


值得注意的是,您可以通过替换来链接当前类中的构造函数 this 对于 base。 - Quibblesome


答案:


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

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

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


1474
2017-08-15 07:40



我想你可能已经错过了这一点。问题是关于在重写构造函数中途调用基础构造函数。也许基本构造函数的数据类型不一样,或者您希望在将其传递到链之前进行一些数据模拟。你会如何实现这样的壮举? - Marchy
如果需要在覆盖的中间调用基础构造函数,则将其提取到可以显式调用的基类上的实际方法。基础构造函数的假设是它们对于安全地创建对象是绝对必要的,因此将始终首先调用基础。 - Jon Limjap
它 是 只是一种你可以随时调用的方法,IL-wise。 C#恰好在此基础上加上了额外的限制。 - Roman Starkov
值得注意的是 base构造函数被调用 之前 访问方法块。 msdn.microsoft.com/en-us/library/ms173115.aspx - John Weisz
如果您需要在构造函数中途调用基类构造函数,那么这不是一个好的设计。构造函数的想法是它完成执行任务所需的所有工作。这样做的结果是,当您的派生构造函数启动时,基类已经完全初始化,派生类可以自由调用任何基类函数。如果你的设计是你想要在构造函数的一半做某事,那么显然这不是初始化基类ans因此不应该在基类的构造函数中,而是在一个单独的,可能受保护的函数中 - Harald Coppoolse


请注意,您可以使用 静态的 调用基础构造函数的方法。

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

420
2018-04-28 17:34



Exception类是如此被锁定,以至于我发现自己这样做了几次,但是请注意,如果你可以避免它,你不应该做的事情。 - SMASH
嗨@ChrisS,我可以使用像`:base(“我的默认消息。”)`,如何使用这样的? - Carlos
对不起,C#newb在这里。你为什么打电话? Trace.WriteLine("message was " + message)? - kdbanman
@kdbanman那只是输出调试信息。没有相关的功能目的。 - Nick Whaley
很好的答案。 接受的答案 不允许我做处理;和 关于变通方法的后续评论  假设我有权更改基类;我不。 工厂答案 假设我可以控制类的实例化方式;我不能。只有你的回答让我在将它传递给基础之前修改一些东西。 - The Red Pea


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

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

77
2018-02-27 02:22



这可以 可能 违反了SOLID原则(SRP),因为创建该类的责任包含在该类假设要处理的任何其他责任中。可以使用抽象工厂,但可能会给简单代码增加不必要的复杂性。当然,如果你知道它会对你的架构产生影响以及如何解决你的设计决策可能引起的任何未来问题,那么违反SOLID就行了。 - Sebastien


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

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


21
2017-12-04 05:03





这是真的使用了 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

16
2017-11-11 11:32



我明白你要解释的是什么,你是对的。如果在一个类中有两个构造函数,则可以使用“this”关键字引用另一个,类似于在调用继承的构造函数时如何使用“base”。然而,这不是OP所要求的,所以这不是真正的添加它的地方。 - IAmTimCorey


框架设计指南 和FxCop规则。

1.自定义异常的名称应以Exception结尾

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

12
2018-01-24 07:34





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

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

要么

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

8
2018-05-27 21:27



你不需要从你的例子中删除单词“class”,因为这些是构造函数...... - MarzSocks


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

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

4
2018-02-26 04:11





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

4
2018-04-07 12:06



这是最好的答案,因为它也包含构造函数重载。 - vibs2006