1856 Stimmen

Aufrufen des Basiskonstruktors in C#

Wenn ich von einer Basisklasse erbe und etwas vom Konstruktor der geerbten Klasse an den Konstruktor der Basisklasse übergeben möchte, wie mache ich das?

Wenn ich z. B. von der Klasse Exception erbe, möchte ich so etwas wie das Folgende tun:

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

Im Grunde, was ich will, ist in der Lage, die Zeichenfolge Nachricht an die Basisklasse Exception übergeben.

37 Stimmen

Es ist auch erwähnenswert, dass Sie Konstruktoren in Ihrer aktuellen Klasse verketten können, indem Sie this para base .

0 Stimmen

5 Stimmen

Anstatt zu sagen, "es fällt alles auseinander", ist es viel hilfreicher, einfach die Fehlermeldung zu posten, die Sie erhalten

24voto

Fab Punkte 12827

De Rahmengestaltungsrichtlinien und FxCop-Regeln. :

1. Die benutzerdefinierte Ausnahme sollte einen Namen haben, der mit Exception endet

    class MyException : Exception

2. Ausnahmen sollten öffentlich sein

    public class MyException : Exception

3. CA1032: Ausnahmen sollten Standardkonstruktoren implementieren.

  • Ein öffentlicher parameterloser Konstruktor.
  • Ein öffentlicher Konstruktor mit einem String-Argument.
  • Ein öffentlicher Konstruktor mit einer Zeichenkette und einer Exception (da er eine andere Exception verpacken kann).
  • Ein Serialisierungskonstruktor, der geschützt ist, wenn der Typ nicht versiegelt ist, und privat, wenn der Typ versiegelt ist. Basierend auf 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.
      }
    }  

oder

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

22voto

dynamiclynk Punkte 2134

Sie können auch eine bedingte Prüfung mit Parametern im Konstruktor durchführen, was eine gewisse Flexibilität ermöglicht.

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

oder

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

0 Stimmen

Ist es möglich, eine Bedingung zu haben, um 2 verschiedene Basiskonstruktoren zu verwenden? Ich meine einen von ihnen mit 2 Parametern und den anderen mit 3 Parametern?

0 Stimmen

@DavidCon sicher können Sie mehrere Konstruktoren mit unterschiedlichen Signaturen erstellen \params in Ihrer Basisklasse, verwenden Sie sie wie oben.

0 Stimmen

Ich kann nicht zu verschiedenen Basiskonstruktoren aufrufen. Ich brauche eine Idee wie diese: public MyClass(object myObject=null): base(myObject==null ? invokeConstructorBaseA: invokeConstructorBaseB){} Außerdem hat ConstructorBaseA 2 Parameter und ConstructorBaseB hat 3 Parameter. Gibt es einen Grund, sie aufzurufen?

17voto

CShark Punkte 2075

Wie einige der anderen hier aufgeführten Antworten zeigen, können Sie Parameter an den Konstruktor der Basisklasse übergeben. Es wird empfohlen, den Konstruktor Ihrer Basisklasse am Anfang des Konstruktors Ihrer geerbten Klasse aufzurufen.

public class MyException : Exception
{
    public MyException(string message, string extraInfo) : base(message)
    {
    }
}

Ich stelle fest, dass Sie in Ihrem Beispiel nie die Option extraInfo Parameter, so dass ich annahm, dass Sie vielleicht die extraInfo String-Parameter an den Message Eigenschaft Ihrer Ausnahme (es scheint, dass dies in der akzeptierten Antwort und dem Code in Ihrer Frage ignoriert wird).

Dazu wird einfach der Konstruktor der Basisklasse aufgerufen und dann die Eigenschaft Nachricht mit den zusätzlichen Informationen aktualisiert.

public class MyException: Exception
{
    public MyException(string message, string extraInfo) : base($"{message} Extra info: {extraInfo}")
    {
    }
}

15voto

springy76 Punkte 3508

Verwendung neuerer C#-Funktionen, nämlich out var können Sie die statische Factory-Methode loswerden. Ich habe gerade herausgefunden (durch Zufall), dass aus var-Parameter von Methoden aufgerufen inse base-"Aufruf" Fluss an den Konstruktor Körper.

Beispiel mit dieser Basisklasse, von der Sie ableiten wollen:

public abstract class BaseClass
{
    protected BaseClass(int a, int b, int c)
    {
    }
}

Der nicht kompilierte Pseudocode, den Sie ausführen möchten:

public class DerivedClass : BaseClass
{
    private readonly object fatData;

    public DerivedClass(int m)
    {
        var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
        base(fd.A, fd.B, fd.C); // base-constructor call
        this.fatData = fd;
    }
}

Und die Lösung durch die Verwendung einer statischen privaten Helper-Methode, die alle erforderlichen Basisargumente (plus zusätzliche Daten, falls erforderlich) und ohne Verwendung einer statischen Factory-Methode, nur einfach Konstruktor nach außen:

public class DerivedClass : BaseClass
{
    private readonly object fatData;

    public DerivedClass(int m)
        : base(PrepareBaseParameters(m, out var b, out var c, out var fatData), b, c)
    {
        this.fatData = fatData;
        Console.WriteLine(new { b, c, fatData }.ToString());
    }

    private static int PrepareBaseParameters(int m, out int b, out int c, out object fatData)
    {
        var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
        (b, c, fatData) = (fd.B, fd.C, fd); // Tuples not required but nice to use
        return fd.A;
    }
}

0 Stimmen

Es hatte Kommentare gegeben - was ist mit ihnen geschehen?

11voto

Donat Sasin Punkte 301
public class MyException : Exception
{
    public MyException() { }
    public MyException(string msg) : base(msg) { }
    public MyException(string msg, Exception inner) : base(msg, inner) { }
}

3 Stimmen

Dies ist die beste Antwort, da sie auch Konstruktorüberladungen enthält.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X