2010-11-18 23 views
7

que estoy teniendo el siguiente problema:problema con los constructores y la herencia en C#

public class A { 
    public A(X, Y, Z) { 
    ... 
    } 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 
     //i want to instantiate Z here and only then pass it to the base class! 
    } 
} 

¿Cómo puedo solucionar este problema? ¿Hay alguna manera?

+0

¿Qué? es 'B: A'? Si es así, ¿cómo puede A tener * más * datos que B? Además, A no parece tener dicho constructor ... – Kobi

+0

¿Te refieres a la clase pública B: A {en tu ejemplo? –

+0

Publicación original editada. Sí, es B: A –

Respuesta

13

La solución común es llamar a un método estático que pertenece al tipo que puede calcular el valor del parámetro que se pasará al constructor base.

Por ejemplo:

public B(int x, int y) 
    : base(x, y, CalculateZ(x, y)) 
{ 

} 

// You can make this parameterless if it does not depend on X and Y 
private static int CalculateZ(int x, int y) 
{ 
    //Calculate it here. 

    int exampleZ = x + y; 

    return exampleZ; 
} 

tenga en cuenta que CalculateZ no puede ser un método de instancia, porque la referencia this no está disponible en inicializadores de constructor.

desde el lenguaje de especificación 10.11.1 inicializadores de constructor:

Una instancia de inicialización del constructor no puede acceder a la instancia de ser creado. Por lo tanto se trata de un error de tiempo de compilación para hacer referencia a este en una expresión argumento de la inicializador constructor, como lo es un error de tiempo de compilación para una expresión argumento para hacer referencia a cualquier instancia miembro a través de un simple nombre.

EDIT: Se cambió 'instancia' a 'estático' en la descripción.

+1

+1, pero ¿no quiere decir que es legal llamar * métodos estáticos *? – LukeH

+0

@Kobi, @LukeH: Fue un error tipográfico con congelación cerebral; la mente piensa una cosa y los dedos escriben otra. Gracias por mencionarlo. – Ani

1
public abstract class A { 
    public A(X, Y) { 
    ... 
    } 

    public abstract Z TheVariableZ{get;set;} 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 
     //i can only calculate Z here! 
    } 

    public override Z TheVariableZ{//implement it here} 
} 

Y si no se puede hacer un resumen, simplemente marcar la propiedad como virtuales

+3

Llamar a un método virtual en un constructor es una mala idea: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

1

Posiblemente esto:

public abstract class A { 
    public A(X, Y) { 
     CalculateZ(); 
    } 

    abstract void CalculateZ(); 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 

    } 

    override void CalculateZ() 
    { 
     ... Calculate here. 
    } 
} 
+3

Llamar a un método virtual en un constructor es una mala idea: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

2

Debe calcular Z antes de llamar al propio constructor. Si es simple puedes usar una expresión en línea, de lo contrario necesitarás definir una función auxiliar.

El uso de un helperfunction:

public class A { 
    public A(X x, Y y, Z z) { 
    ... 
    } 
} 

public class B : A { 
    private static Z calculateZ() 
    { 
    } 

    public B(X x, Y y) : base(X, Y, calculateZ()) { 

    } 
} 

Sin helperfunction:

public B(X, Y) : base(X, Y, X+Y) { 

}