2010-09-02 15 views
6

Lassen Sie uns sagen, dass ich eine Klasse (ClassA) enthält, ein Verfahren, das den Konstruktor einer anderen Klasse aufruft, wie folgt aus:Warum muss ich in nicht verwendeten Konstruktoren auf Typen verweisen?

public class ClassA 
{ 
    public void CallClassBConstructor() 
    { 
     using(ClassB myB = new ClassB()) {...} 
    } 
} 

Die Klasse ClassB wie folgt aussieht:

public class ClassB : IDisposable 
{ 
    public ClassB(){} 
    public ClassB(string myString){} 
    public ClassB(ClassC myC){} 
    public void Dispose() {...} 
} 

... und ClassC ist noch einfacher:

public class ClassC{} 

Wenn ich diese Klassen in ihren eigenen Arsch embly und kompilieren Sie die ganze Lösung Ich bekomme keine Fehler. Aber wenn ich die Anweisung using mit diesem ersetzen:

using(ClassB myB = new ClassB("mystring")){...} 

ich einen Kompilierungsfehler fragen mich einen Verweis auf [mynamespace].ClassC in ClassA hinzuzufügen. Da ich überhaupt nicht ClassB(ClassC myC) anrufe, macht das für mich keinen Sinn - warum muss ich die Typen anderer Konstruktoren einbeziehen, egal ob ich sie verwende oder nicht? Was wäre, wenn ClassC in einer lizenzierten oder schwer zu erwerbenden Baugruppe enthalten wäre? Ist das ein Beispiel für schlechtes Design, das Entwickler vermeiden sollten, oder fehlt mir hier etwas?

+3

Dies kann nicht an erster Stelle kompiliert werden, ClassB implementiert IDisposable nicht. Dann kann es nicht in einer using-Klausel verwendet werden. –

+0

Dies ist nicht C/C++, wo ungültiger nicht verwendeter Code automatisch ignoriert wird, wenn die Abschnitte vom Linker bearbeitet werden. – leppie

+0

Ich bearbeitet den Code, so dass es jetzt kompilieren sollte –

Antwort

9

Es hat mit der Methode Überladung Auflösung zu tun, wenn der ClassB Konstruktor aufrufen.

Wenn Sie den Konstruktor ohne Parameter aufrufen, gibt es keine Konflikte. Es gibt nur einen Kandidaten, also ist es gewählt. Es ist in diesem Fall nicht notwendig, ClassA auf ClassC zu verweisen.

Wenn Sie jedoch den Konstruktor mit einem Parameter aufrufen, dann sind am Anfang beide Einzelparameterkonstruktoren Kandidaten. Um diesen Aufruf aufzulösen, muss der Compiler über ClassC wissen. Soweit Sie wissen, könnte ClassC beispielsweise einen impliziten Konvertierungsoperator enthalten.

(Natürlich wissen wir, dass in diesem speziellen Beispiel solch ein impliziter Konvertierungsoperator sowieso nicht ausgelöst würde, weil es eine perfekte Übereinstimmung gibt, die eine Zeichenfolge annimmt - aber die Methodenüberladungsauflösungsregeln sind so definiert, dass sie sehr gut sind Stellen Sie sich vor, dass es so entworfen wurde, dass das Hinzufügen einer Referenz dazu führen kann, dass Ihr Code plötzlich eine andere Konstruktorüberladung aufruft.)

+0

Danke Timwi, ich denke, alle Antworten haben es mir ziemlich klar gemacht :-) –

+0

How Eine fehlende 'using'-Anweisung ist nicht genug für den Compiler zu wissen, welche Überladung zu verwenden? Ich bin verwirrt, dass das einfache Hinzufügen der Referenz den Compiler glücklich macht. – Stijn

+0

@Stijn: Sie meinen wahrscheinlich die ['using' Richtlinie] (http://msdn.microsoft.com/en-us/library/sf0df423.aspx), * nicht * die [' using' Anweisung] (http://msdn.microsoft.com/en-us/library/yh598w02.aspx). Aber weder die Frage noch meine Antwort haben etwas damit zu tun, wie man Anweisungen benutzt oder benutzt. Sie sind über [Referenzen zu anderen Baugruppen] (http://msdn.microsoft.com/en-us/library/wkze6zky%28v=vs.80%29.aspx). Die 'using'-Deklaration fügt keine solche Referenz hinzu. – Timwi

1

Um die Überladungen des Konstruktors aufzulösen, muss der Compiler die beteiligten Typen kennen. I.e. es muss ClassC wissen, um die richtige Überladung des Konstruktors für ClassB auszuwählen.

+0

Danke für Ihre Antwort Brian - es stimmte gut mit den anderen Antworten –

1

Es ist, weil ClassC, die Sie in einer separaten Assembly platziert haben, Teil der öffentlichen Schnittstelle von ClassB ist, da es ein Parameter von einem der Konstruktoren ist. Sie müssen auf die enthaltene Assembly dieses Typs verweisen, da der Compiler ansonsten keine Informationen dazu hat, wie die Typinformationen aufgelöst werden. In diesem speziellen Fall muss der Compiler alle Parametertypen von allen Überladungen des Konstruktors auflösen, so dass er den richtigen auswählen kann, aber dies ist kein Elementüberlastungsproblem per se. Dies geschieht immer dann, wenn der Compiler Typinformationen auflösen muss. Dies kann auch bei Rückgabetypen vorkommen.

+0

Warum der Downvote? Schon vor meiner Bearbeitung war diese Antwort nicht falsch. –

+0

Es tut mir leid, dass ich neu in stackoverflow bin, aber ich habe nichts angeklickt, nur die Seite neu geladen. Vielleicht wurde das deshalb abgelehnt? –

+0

@boomshanka: Nein, es war nichts, was du getan hast. Jemand dachte, diese Antwort sei entweder falsch oder schädlicher als hilfreich. Ich stehe hinter meiner Antwort. –

Verwandte Themen