2009-03-09 17 views
13

que tiene la siguiente jerarquía:Calling constructor base en C#

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 

    string sMessage = "Blah " + someParams; 

    //Here I want to call the base constructor 
    //base(sMessage); 

    } 

} 

Respuesta

16

Tienes que llamar al constructor de la clase base antes del cuerpo del constructor de la clase derivada.

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 

    } 

} 
+0

Esta es probablemente la mejor solución para este caso simple, pero se pondría muy fea rápidamente si la construcción del parámetro fuera mucho más compleja. – tvanfosson

+0

Eso es cierto, aunque también podría construir el parámetro en un método estático y pasar el resultado al constructor de la clase base. Prefiero ese enfoque sobre el gancho. O bien, dado que se trata de .NET, podría eliminar las cosas del constructor y hacerlo en los setters, que es amigable con la serialización. – OregonGhost

7

No se puede. Se le puede llamar antes:

public Derived() : base() 

o tiene que utilizar un gancho

class Base 
{ 
    protected void init() { } 
    public Base(string sMessage) 
    { 
    init(); 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 
    string sMessage = "Blah " + someParams; 
    init(); 
    } 
} 
+0

Dado que se supone que el constructor Base debe hacer cosas (presumibles algunas cosas con sMessage), ¿cómo resuelve este problema? – wcm

+0

Si usa el gancho, debe tener una forma de evitar llamar al constructor base predeterminado. Vea mi respuesta para una forma de evitar esto proporcionando un constructor que no ejecute el inicializador. – tvanfosson

+0

@wcm: Solo estoy mostrando los pasos para lograr el orden de las operaciones que DotnetDude necesita. Parece que entiende C# lo suficientemente bien como para alterar los parámetros y devolver el objeto para que se ajuste a sus necesidades reales desde aquí. – Dinah

0
public Derived(string someParams) : base(someParams) 
{ 
    string sMessage = "Blah " + someParams; 
} 

Ésta es la manera que tiene que hacerlo. Usted tal vez podría poner el código que desea llamar después en un método protegido en la clase base y luego se le puede llamar después de esta manera:

class Base 
{ 
    public Base(string sMessage) 
    { 
    ConstructorStuff(); 
    } 

    protected Base() 
    { 
    } 

    protected void ConstructorStuff() 
    { 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    {  
    string sMessage = "Blah " + someParams; 

    ConstructorStuff();  
    }  
} 
+1

Esto ejecutará ConstructorStuff dos veces: una vez cuando se invoca el constructor base por defecto antes del constructor derivado y una vez durante la ejecución del constructor derivado. – tvanfosson

+0

Erm? Base no tiene un constructor predeterminado que llame a ConstructorStuff? –

+1

Ah.Luego debe proporcionar un constructor predeterminado o el código no se compilará ya que su clase derivada lo necesitará. El problema sigue siendo que el constructor predeterminado necesitará usar también ConstructorStuff y necesita una alternativa que no invoque el inicializador. – tvanfosson

1

Puntos Para anotar en constructores:

· Los constructores no pueden ser "virtual".

· No se pueden heredar.

· Los constructores se llaman en el orden de herencia.

public Child(string a):base(a){} 
4

Si realmente necesita tener su carrera constructor de primera, a continuación, se sugiere emplear un método de inicialización protegida que se invoca por sus constructores y hace el trabajo real de la inicialización de la clase. Debe proporcionar un constructor alternativo que permita omitir la inicialización.

public class Base 
{ 

    public Base() : this(true) { } 

    protected Base(bool runInitializer) 
    { 
     if (runInitializer) 
     { 
      this.Initialize(); 
     } 
    } 

    protected void Initialize() 
    { 
     ...initialize... 
    } 
} 

public class Derived : Base 
{ 
    // explicitly referencing the base constructor keeps 
    // the default one from being invoked. 
    public Derived() : base(false) 
    { 
     ...derived code 
     this.Initialize(); 
    } 
} 
0

En realidad, la solución más simple es:

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 
    } 

} 

¿Por qué hacer que sea más complicado?

+0

Sí, me di cuenta después de que OregonGhost ya sugirió esto ... –

6

originalmente se perdió el comentario de OregonGhost sobre el uso de un método estático para modificar el parámetro, que resultó ser el más útil para mí, así que pensé que me gustaría añadir un código de ejemplo para otros que leen en este tema:

class Base 
{ 
    public Base(string sMessage) 
    { 
     // Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string sMessage) : base(AdjustParams(sMessage)) 
    { 
    } 

    static string AdjustParams(string sMessage) 
    { 
     return "Blah " + sMessage; 
    } 
} 
Cuestiones relacionadas