2010-11-01 2 views
44

In C#, der folgende Code nicht kompiliert:Warum können C# -Membernamen nicht mit dem umschließenden Typnamen übereinstimmen?

class Foo { 

    public string Foo; 

} 

Die Frage ist: Warum?

Genauer gesagt, ich verstehe, dass dies nicht kompilieren, weil (ich zitiere):

Mitgliedsnamen können nicht die gleiche sein wie ihre einschließenden Typ

Ok, gut. Ich verstehe das, ich werde es nicht noch einmal tun, das verspreche ich.

Aber ich verstehe wirklich nicht warum der Compiler weigert sich, ein Feld mit dem gleichen Namen wie ein umschließender Typ zu nehmen. Was ist das zugrunde liegende Problem, das mich daran hindert?

Antwort

43

Streng genommen ist dies eine Einschränkung, die von C# auferlegt wird, höchstwahrscheinlich für die Bequemlichkeit der Syntax. Ein Konstruktor hat einen Methodenkörper, aber sein Membereintrag in IL wird als ".ctor" bezeichnet und er hat geringfügig andere Metadaten als eine normale Methode (In den Reflection-Klassen wird ConstructorInfo von MethodBase abgeleitet, nicht von MethodInfo.) Ich glaube nicht Es gibt eine .NET-Einschränkung, die verhindert, dass ein Member (oder sogar eine Methode) mit demselben Namen wie der äußere Typ erstellt wird, obwohl ich es nicht versucht habe.


Ich war neugierig, also bestätigte ich, dass es keine .NET-Beschränkung ist. Erstellen Sie die folgende Klasse in VB:

Public Class Class1 
    Public Sub Class1() 

    End Sub 
End Class 

In C#, Sie verweisen sie als:

var class1 = new Class1(); 
class1.Class1(); 
+1

Dies ist wahrscheinlich die beste, vollständigste Antwort hier. In VB (ich glaube, ich habe gerade ein wenig in den Mund gekotzt) der Ctor ist Sub New() ... –

+0

Meinst du "verhindert die Schaffung eines Mitglieds" die Art, wie er es in der Frage beschreibt? Ja, das ist der ganze Grund für diese Frage. Wenn du meinst wie 'public string Foo {erhalten; set;} public void Foo() {}', dann ist das auch nicht erlaubt. – jcolebrand

+1

Die Frage ist, ob nur C# es nicht erlaubt oder wenn das .net-Typsystem es nicht erlaubt. Und ich denke, es ist nur C#. – CodesInChaos

18

Da Foo als der Name des Konstruktors reserviert ist.

Also, wenn Ihr Code erlaubt war - was würden Sie den Konstruktor nennen?

Auch wenn es möglich wäre, dies zu tun, indem man den Konstruktor als Sonderfall behandelt und neue Regeln in die Methode/Stabbindung einführt - wäre das eine gute Idee? Es würde irgendwann zu Verwirrung führen.

+3

Aber der Konstruktor ist keine Methode oder irgendetwas, es sollte den Rest des Codes nicht stören. –

+8

Der Konstruktor ist eine Methode.Warum denkst du, ist es nicht? Z.B. Sie können es von einem Konstruktor in einem abgeleiteten Objekt aufrufen. –

+1

@ James Gaunt, weil es nichts zurückgibt, ist es ein [Konstruktor] (http://en.wikipedia.org/wiki/Constructor_%28object-oriented_programming%29). Ich bin mir nicht sicher, wie es in C# funktioniert, aber in Java hat ein Konstruktor nichts mit einer Methode zu tun, außer dass es sich um einen Codeblock handelt. Nennst du es nicht mit 'base()'? Also sollte es auch hier kein Problem geben. –

2

Weil der Mitgliedsname mit dem Namen des Konstruktors der Klasse kollidiert?

0

Es gibt einen richtigen Weg, es zu tun und einen falschen Weg, es zu tun.

Warum lässt C# es nicht zu?

Weil es keinen Grund dazu gibt. Warum möchtest du solche Verwirrung in deinem Leben schaffen?

Ich denke, die CLR erlaubt es, wie ein anderer Beitrag beweist mit einem vb.net Beispiel und es sollte nicht eingeschränkt werden, aber ich würde nicht eine Anwendung basierend auf den gleichen Regeln erstellen möchten, dass die CLR arbeitet. Die Abstraktion macht den Code klarer. Ich denke, das Argument funktioniert auf der gleichen Ebene wie die Mehrfachvererbung. Ja, es kann in einigen Sprachen gemacht werden, aber es verursacht Verwirrung. Meine Antwort wäre daher, Mehrdeutigkeit und Verwirrung zu reduzieren und basiert auf dem C# Parser/Compiler. Eine Design-Entscheidung des C# -Teams.

Verwandte Themen