2009-03-25 14 views
3

Warum verursacht der erste Konstruktor in ClassA den Compiler-Fehler 'kann "this" in Member Intializer' nicht verwenden?Konstruktor verkettet mit "diesem"

... oder wie kann ich das zum Funktionieren bringen?

Dank

public sealed class ClassA : IMethodA 
{ 
    private readonly IMethodA _methodA; 

    public ClassA():this(this) 
    {} 

    public ClassA(IMethodA methodA) 
    { 
     _methodA = methodA; 
    } 

    public void Run(int i) 
    { 
     _methodA.MethodA(i); 
    } 

    public void MethodA(int i) 
    { 
     Console.WriteLine(i.ToString()); 
    } 
} 

public interface IMethodA 
{ 
    void MethodA(int i); 
} 

Antwort

1

Sie können nicht die this Schlüsselwort verwenden, wenn Konstrukteuren im Wesentlichen Verkettungs weil this auf ein Objekt verweist, die bisher noch nicht (Erstellung des Objekts instanziiert hat beginnt erst einige (der obersten Ebene oder Base) Konstruktorblock wurde eingegeben). Außerdem, warum genau möchten Sie das tun? Es scheint ziemlich sinnlos, wenn Sie überall Zugriff auf das Schlüsselwort this haben.

ich einfach empfehlen die Verwendung von unabhängigen Konstrukteuren als solche:

public sealed class ClassA : IMethodA 
{ 
    private readonly IMethodA _methodA; 

    public ClassA() 
    { 
     _methodA = this; 
    } 

    public ClassA(IMethodA methodA) 
    { 
     _methodA = methodA; 
    } 
} 

Vielleicht falsch verstehen ich, was Sie zu tun versuchen, aber hoffentlich, dass das Problem für Sie zu lösen.

9

Sie dürfen die this(...) Syntax verwenden anderen Konstruktor auf dem gleichen Niveau zu berufen - aber kann man nicht this (die aktuelle Instanz) in diesem Zusammenhang verwenden.

Die einfachste Möglichkeit besteht darin, den Zuweisungscode zu duplizieren (_methodA = methodA).

Eine weitere Option könnte null-koaleszierenden sein:

public ClassA():this(null) 
{} 

public ClassA(IMethodA methodA) 
{ // defaults to "this" if null 
    _methodA = methodA ?? this; 
} 
+0

@Marc Gravell: schlagen Sie mich dazu ... –

3

Diese 10.11.1 des C# spec in Abschnitt genannt wird aus

Ein Instanzkonstruktors initializer kann nicht die Instanz zugreifen zu erstellt . Daher ist es ein Kompilierzeitfehler dieses in einem Argumente Expression des Konstruktor Initialisierer referenzieren, wie es ist, ein Kompilierzeitfehler für ein Argument Ausdruck jede Instanz Element durch einen einfachen Namen zu referenzieren.

Es gibt keine Möglichkeit, dies mit einem Instanzkonstruktor zu erreichen, da auf diesen nicht zugegriffen werden kann. Sie können den Konstruktor privat machen, eine Initialisierungsmethode und einen statischen Konstruktor erstellen.

public sealed class ClassA : IMethodA {  
    private ClassA() { } 
    private void Initialize(IMethodA param) { ... } 
    public static ClassA Create() { 
    var v1 = new ClassA(); 
    v1.Initialize(v1); 
    return v1; 
    } 
    public static ClassA Create(IMethodA param) { 
    var v1 = new ClassA(); 
    v1.Initialize(param); 
    return v1; 
    } 
} 
3

Sie versuchen, das Objekt zu übergeben, bevor es erstellt wird. Obwohl der Compiler in diesem Fall etwas Sinnvolles tun könnte, wird das im Allgemeinen nicht funktionieren.

Ihr aktuelles Beispiel funktioniert, wenn Sie dies nur tun:

public ClassA() 
    { 
    _methodA = this; 
    } 

Aber Sie wollen wahrscheinlich mehr Logik teilen, so dass nur eine Funktion.

public ClassA() 
    { 
    SetStuff(); 
    _methodA = this; 
    } 

    public ClassA(IMethodA methodA) 
    { 
    SetStuff(); 
    _methodA = methodA; 
    } 
+0

Beachten Sie, dass Sie SetStuff immer noch mit readonly-Feldern verwenden können ... * wenn * Sie ein 'ref' /' out'-Argument verwenden. Ob es sich lohnt, hängt vom Szenario ab. –