2010-11-18 2 views
7

Je rencontrais le problème suivant:problème avec les constructeurs et l'héritage 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! 
    } 
} 

Comment puis-je résoudre ce problème? Y a-t-il un moyen?

+0

Quoi? est 'B: A'? Si oui, comment A peut-il avoir * plus * de données que B? En outre, A ne semble pas avoir un tel constructeur ... – Kobi

+0

Voulez-vous dire classe publique B: A {dans votre exemple? –

+0

Article original modifié. Oui, son B: A –

Répondre

13

La solution commune est d'appeler une méthode statique appartenant au type Cela permet de calculer la valeur du paramètre à transmettre au constructeur de base.

Par exemple:

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

Notez que la CalculateZ ne peut pas être une méthode d'instance, car la référence this n'est pas disponible dans initializers constructeur.

de la langue spécification 10.11.1 constructeur initializers:

Une instance constructeur ne peut pas initialiseur accéder à l'instance étant créé. Par conséquent, il est une erreur de compilation pour faire référence à cette dans une expression d'argument de la initialiseur constructeur , comme une erreur de compilation pour une expression arguments pour faire référence à toute instance membre par un simple nom.

EDIT: modification de 'instance' en 'static' dans la description.

+1

+1, mais ne voulez-vous pas dire qu'il est légal d'appeler * méthodes statiques *? – LukeH

+0

@Kobi, @LukeH: était une faute de frappe du cerveau; l'esprit pense une chose et les doigts en tapent un autre. Merci de l'avoir signalé. – 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} 
} 

Et si vous ne pouvez pas faire un résumé, indiquant simplement que la propriété virtuelle comme

+3

L'appel d'une méthode virtuelle dans un constructeur est une mauvaise idée: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

1

Peut-être ceci:

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

Appel d'une méthode virtuelle dans un constructeur est une mauvaise idée: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

2

Vous devez calculer Z avant que le constructeur ne soit appelé. Si c'est simple, vous pouvez utiliser une expression en ligne, sinon vous aurez besoin de définir une fonction d'assistance.

L'utilisation d'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()) { 

    } 
} 

Sans helperfunction:

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

} 
Questions connexes