2012-05-26 5 views
17

Let dire che abbiamo Classe A e Classe B. ClassB estende la classe A. (ClassB: ClassA)chiamata costruttore di base dopo l'esecuzione di codice

Ora diciamo che ogni volta che un'istanza di ClassB, mi piace correre qualche caso codice e solo dopo chiamare "base" per raggiungere il costruttore ClassA.

come:

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

Nel linguaggio di programmazione solito lavoro con, posso farlo, semplicemente chiamando super() dopo Console.WriteLine(); Ma non posso farcela in C#. C'è qualche altra sintassi o altro modo per farlo?

+0

Non c'è modo di farlo utilizzando il costruttore di base in C#. Puoi estrarre il login in un metodo di base e chiamarlo usando * base.Method() *. – decyclone

+0

Non puoi farlo con C# –

+3

Con quale lingua lavori normalmente? Perché se si tratta di Java, ti sbagli: non puoi farlo lì ... –

risposta

22

C'è un modo hacky di farlo usando un inizializzatore variabile di istanza:

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

Il meno modo hacky di farlo è quello di ripensare a come si costruisce un ClassB per cominciare. Invece di avere clienti chiamare direttamente la funzione di costruzione, di fornire un metodo statico per loro di chiamare:

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

C# non consente il richiamo di costruttori di base all'interno di corpi del costruttore, diversi da Java.

1

Non è possibile farlo con C#. La soluzione migliore è estrarre quel codice nel proprio metodo nel genitore e poi chiamarlo dal bambino quando sei pronto.

0

Non è possibile chiamare il costruttore base. Ma una cosa diversa è che quando si dichiara un oggetto di classe derivata viene chiamato sia costruttore derivato che 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

Un altro trucco se si può ottenere via con chiamare un metodo statico.

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

Recentemente mi sono imbattuto in uno scenario in cui avevo bisogno di calcolare una certa logica, prima di passare il risultato in base.

ho potuto solo fare qualcosa di simile

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

} 

ma trovo che per essere brutto, e può ottenere veramente lungo in orizzontale. Quindi ho optato invece per usare i metodi di Func Anonymous.

E.g. immaginate di avere una classe base,

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

Ora si eredita da quella e vogliono fare un po 'di logica per determinare il testo della query 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! 
    } 

} 

In questo modo è possibile eseguire codice prima base si chiama e (secondo me) non è veramente hacky.

+0

Realmente esagerato nel pensare di avere accesso alla classe base per rendere il param un func. – Kukks

+0

Eredita la classe base e sovraccaricherà il costruttore. Poi ereditalo. –

4

Un'altra soluzione elegante sarebbe quella di ripensare completamente come sono costruiti i tuoi oggetti.Nel costruttore della classe base è possibile chiamare la propria funzione construct, e si omette costruttori futuri dipendenti, nel seguente modo:

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

Ho avuto lo stesso problema. Ho trovato questa soluzione la migliore se non hai accesso alla classe 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); 
    } 
} 
Problemi correlati