2012-05-26 10 views
17

Digamos que tenemos Clase A y Clase B. ClassB extiende Clase A. (ClassB: ClassA)llamada al constructor base después de la ejecución de código

Ahora vamos a decir que cada vez que crear una instancia ClassB, me gustaría hacer algunas aleatoria código y solo luego llame a "base" para llegar al constructor de ClassA.

igual:

class ClassA 
{ 
    public ClassA() 
    { 
     Console.WriteLine("Initialization"); 
    } 
} 

class ClassB : ClassA 
{ 
    public ClassB() //: base() 
    { 
     // Using :base() as commented above, I would execute ClassA ctor before               //   Console.WriteLine as it is below this line... 
     Console.WriteLine("Before new"); 
     //base() //Calls ClassA constructor using inheritance 
     //Run some more Codes here... 
    } 
} 

En el lenguaje de programación por lo general trabajo con, puedo hacer eso, simplemente llamando super() después Console.WriteLine(); Pero no puedo hacerlo en C#. ¿Hay alguna otra sintaxis u otra forma de hacer eso?

+0

No hay forma de hacerlo utilizando el constructor base en C#. Puede extraer el inicio de sesión en un método base y llamarlo usando * base.Method() *. – decyclone

+0

No puede hacer eso con C# –

+3

¿Con qué idioma generalmente trabaja? Porque si se trata de Java, estás equivocado, tampoco puedes hacer eso ... –

Respuesta

22

Hay una manera hacky de hacerlo utilizando una variable de instancia inicializador:

using System; 

class ClassA 
{ 
    public ClassA() 
    { 
     Console.WriteLine("Initialization"); 
    } 
} 

class ClassB : ClassA 
{ 
    private readonly int ignoreMe = BeforeBaseConstructorCall(); 

    public ClassB() 
    { 
    } 

    private static int BeforeBaseConstructorCall() 
    { 
     Console.WriteLine("Before new"); 
     return 0; // We really don't care 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     new ClassB(); 
    }  
} 

El menos manera hacky de hacerlo es a repensar cómo se construye un ClassB para empezar. En lugar de tener los clientes llaman directamente al constructor, proporcionar un método estático para que llamen:

public static ClassB CreateInstance() 
{ 
    Console.WriteLine("Before initialization stuff"); 
    return new ClassB(); 
} 
0

C# no permite llamar a los constructores base dentro de cuerpos constructores, diferentes de Java.

1

No puede hacer eso con C#. Su mejor opción es extraer ese código en su propio método en el padre y luego llamarlo cuando esté listo.

0

No puede llamar al constructor base. Pero una cosa diferente es que cuando declaras un objeto de clase derivada se llama tanto al constructor derivado como a la base.

class ClassA 
{ 
    public ClassA() 
    { 
     Console.WriteLine("Initialization"); 
    } 
} 

class ClassB : ClassA 
{ 
    public ClassB() //: base() 
    { 
     // Using :base() as commented above, I would execute ClassA ctor before               //   Console.WriteLine as it is below this line... 
     Console.WriteLine("Before new"); 
     //base() //Calls ClassA constructor using inheritance 
     //Run some more Codes here... 
    } 
} 
void main(string[] args) 
    { 
     ClassB b = new ClassB(); 

    } 
3

Otro truco si puede salirse con llamar a un método estático.

public class ClassA 
{ 
    public ClassA() 
    { 
     Debug.WriteLine("Call A Constructor"); 
    } 
} 

public class ClassB:ClassA 
{ 
    public ClassB():this(aMethod()) 
    { 
    } 

    private ClassB(object empty):base() 
    { 
     Debug.WriteLine("Class B Second Constructor"); 
    } 

    private static object aMethod() 
    { 
     Debug.WriteLine("Run me First"); 
     return null; 
    } 
} 
0

Recientemente me encontré con un escenario en el que necesitaba calcular algo de lógica antes de pasar el resultado a la base.

tan sólo pudiera hacer algo como

public SomeConstructor: base(FlagValue == FlagValues.One || FlagValues.Two ? "OptionA" : "OptionB") 
{ 

} 

pero me parece que para ser fea, y se puede volver muy larga en sentido horizontal. Así que opté por utilizar los métodos de Func Anonymous.

E.g. imagine que tiene una clase base,

public class SomeBaseClass 
{ 
    public SomeBaseClass(Func<string> GetSqlQueryText){ 
    string sqlQueryText = GetSqlQueryText(); 
    //Initialize(sqlQueryText); 
    } 
} 

Ahora se heredan de eso y querer hacer algo de lógica para determinar el texto de la consulta SQL,

public class SomeSqlObject : SomeBaseClass 
{ 
    public SomeSqlObject(ArchiveTypeValues archiveType) 
     : base(delegate() 
     { 
      switch (archiveType) 
      { 
       case ArchiveTypeValues.CurrentIssues: 
       case ArchiveTypeValues.Archived: 
        return Queries.ProductQueries.ProductQueryActive; 
       case ArchiveTypeValues.AllIssues: 
        return  string.Format(Queries.ProductQueries.ProductQueryActiveOther, (int)archiveType); 
       default: 
        throw new InvalidOperationException("Unknown archiveType"); 
      }; 
     }) 
    { 
     //Derived Constructor code here! 
    } 

} 

De esta manera se puede ejecutar código antes de Base se llama y (en mi opinión) no es realmente hacky.

+0

Es realmente exagerado pensar que tienes acceso a la clase base para hacer que el parámetro sea una función. – Kukks

+0

Heredar la clase base y sobrecargar el constructor. Entonces hereda eso. –

4

Otra solución elegante sería replantearse completamente cómo se construyen sus objetos.En el constructor de la clase base puede llamar a su propia función construct, y omitir los constructores futuros dependientes, de la siguiente manera:

public class ClassA 
{ 
    public ClassA() 
    { 
     Construct(); 
    } 

    public virtual void Construct() 
    { 
     Console.WriteLine("3"); 
    } 
} 

public class ClassB : ClassA 
{ 
    public override void Construct() 
    { 
     Console.WriteLine("2"); 
     base.Construct(); 
    } 
} 

public class ClassC : ClassB 
{ 
    public override void Construct() 
    { 
     Console.WriteLine("1"); 
     base.Construct(); 
    } 
} 
0

que tenían el mismo problema. Encontré que esta solución es la mejor si no tienes acceso a la clase base.

public class BaseClass 
{ 
    public BaseClass(string someValue) 
    { 
     Console.WriteLine(someValue); 
    } 
} 

public class MyClass : BaseClass 
{ 
    private MyClass(string someValue) 
     : base(someValue) 
    { 
    } 

    public static MyClass GetNewInstance(string someValue, bool overrideValue = false) 
    { 
     if (overrideValue) 
     { 
      someValue = "42"; 
     } 
     return new MyClass(someValue); 
    } 
} 
Cuestiones relacionadas