Sollte eine Immobilie den gleichen Namen wie ihr Typ haben?

70

Ich habe manchmal Code gesehen, der so geschrieben wurde:

public class B1
{
}

public class B2
{
    private B1 b1;

    public B1 B1
    {
        get { return b1; }
        set { b1 = value; }
    }
}

dh Klasse B2 hat eine Eigenschaft mit dem Namen "B1", die ebenfalls vom Typ "B1" ist.

Mein Bauchgefühl sagt mir, dass dies keine gute Idee ist, aber gibt es technische Gründe, warum Sie vermeiden sollten, einer Immobilie den gleichen Namen wie ihrer Klasse zu geben?

(Ich benutze .net 2.0, falls das wichtig ist).

Moe Sisko
quelle
Ich glaube, dass die .NET Framework-Designrichtlinien auch diese Namenskonvention empfehlen.
NotDan
1
Welche Namenskonvention - sie gleich nennen oder den Fall der Differenzierung ändern?
Niico

Antworten:

63

Das ist gut. Das kanonische Beispiel hier ist

public Background {
    public Color Color { get; set; }
}

Es gibt seltene Probleme (Eckfälle), die hier auftreten, aber nicht genug, um die Vermeidung dieses Geräts zu rechtfertigen. Ehrlich gesagt finde ich dieses Gerät sehr nützlich. Ich würde es nicht genießen, wenn ich nicht in der Lage wäre, Folgendes zu tun:

class Ticker { ... }


public StockQuote {
    public Ticker Ticker { get; set; }
}

Ich möchte nicht sagen müssen Ticker StockTickeroder Ticker ThisTickeretc.

Jason
quelle
13
class A { public static void Method(int i) { } public void Method(object o) { } }und class B { A A { get; set; } public B() { A = new A(); A.Method(0); } }. Wird den A.MethodAufruf der statischen Methode mit dem Namen Methododer ist es die Instanz Methode mit dem Namen aufrufen Method? (In C # es stellt sich heraus , dass es die statische Methode aufrufen. Wenn Sie jedoch das Ersetzen 0in A.Method(0)durch "Hello, world!"sie die Instanz - Methode aufrufen wird. Beachten Sie, dass Intellisense dies nicht abholen und wird das Highlight Ain A.Method("Hello, world!")blau , als ob es die statische waren Methode.)
Jason
2
Dies soll lediglich darauf hinweisen, dass es (seltene) Fälle geben kann, in denen die Absicht des Codes, der dieses Muster verwendet, nicht kristallklar ist (es gibt natürlich immer eine eindeutige Interpretation basierend auf der Sprachspezifikation).
Jason
1
@ jason Eigenschaften Ich stimme zu, aber Objekte warum? Möchten Sie Ihre statischen (Klassen-) Methodenaufrufe nicht von Ihren Instanzaufrufen unterscheiden? Wenn Sie ein Objekt haben, sehe ich keinen Grund dafür A = new A(), tun Sie es einfach a = new A(). Es ist keine Belastung mehr, aber viel klarer. Ihr Randfall betrifft Objekte, keine Eigenschaften. Sie haben jedoch die Frage zu Objekten geschlossen. In VB unterscheiden Intellisense und Umbenennung nicht zwischen Klassen- und Instanzreferenzen, wenn Objekt und Klasse denselben Namen haben. Das Umbenennen von Eigenschaften mit demselben Namen wie der Typ ist jedoch kein Problem.
Jason S
@Jason In dieser Frage finden Sie Probleme beim Umbenennen in VB-Projekten, wenn Objekte den gleichen Namen wie ihre Klasse haben. Dies gilt nicht für Eigenschaften, aber meine Frage zum Benennen von Objekten mit ihrer Klasse wurde als Duplikat dieser geschlossen.
Jason S
@ Jason Ihr Rand Fall auch bedeutet , dass , wenn Sie die umbenennen Objekt Referenz, Ain A=new A()zu abeispielsweise A.Method("Hello, world!")wird nicht umbenannt werden, ein zu verursachen NullReferenceExceptionzur Laufzeit. Ein weiterer Grund, Objekte nicht mit der Klasse zu benennen, aber dies ist kein Problem mit Eigenschaften! Das Umbenennen der Eigenschaft mit demselben Namen wie der Rückgabetyp ist kein Problem.
Jason S
17

In der Microsoft-Namensrichtlinie für Mitglieder heißt es :

Geben Sie einer Eigenschaft den gleichen Namen wie ihrem Typ.

Wenn Sie eine Eigenschaft haben, die stark in eine Aufzählung eingegeben wurde, kann der Name der Eigenschaft mit dem Namen der Aufzählung identisch sein. Wenn Sie beispielsweise eine Aufzählung mit dem Namen haben CacheLevel, kann auch eine Eigenschaft benannt werden, die einen ihrer Werte zurückgibt CacheLevel.

Obwohl ich zugebe, dass es ein wenig Unklarheit gibt, ob sie dies nur für Enums oder für Eigenschaften im Allgemeinen empfehlen.

Dan Diplo
quelle
12

Ich kann mir nur einen Nachteil vorstellen. Wenn Sie so etwas machen wollten:

public class B1
{
        public static void MyFunc(){ ; }
}

public class B2
{
        private B1 b1;

        public B1 B1
        {
                get { return b1; }
                set { b1 = value; }
        }

        public void Foo(){
                B1.MyFunc();
        }
}

Sie müssten stattdessen verwenden:

MyNamespace.B1.MyFunc();

Ein gutes Beispiel hierfür ist die allgemeine Verwendung in der Winforms-Programmierung, bei der sich die System.Windows.Forms.Cursor-Klasse mit der System.Windows.Forms.Form.Cursor-Eigenschaft überschneidet, sodass Ihre Formularereignisse über den vollständigen Namespace auf statische Elemente zugreifen müssen .

MiffTheFox
quelle
11

Erst heute hat Eric über das Problem 'Farbe Farbe' gebloggt.

http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx

Persönlich würde ich es wenn möglich vermeiden.

SolutionYogi
quelle
4
Warum? Ich sehe keinen Schaden daran.
Steven Sudit
1
@StevenSudit IMO erhöht die Komplexität für den Programmierer (schließlich müssen Sie diesen Artikel lesen, um zu verstehen, was vor sich geht), und wir Programmierer wissen, wie schlecht und fehleranfällig das ist. Ich würde es auch vermeiden.
MasterMastic
3
Was sein Artikel tatsächlich zeigt, ist, dass es dumm ist, sowohl statische als auch Instanzmitglieder mit demselben Namen zu haben. Was ich hoffen würde, würde jeder Programmierer vermeiden. Beachten Sie diesen Schlüsselsatz " In realen Situationen haben die Instanz und die statischen Methoden normalerweise unterschiedliche Namen ". Beachten Sie, dass die Probleme alle auftreten, weil er static Mund (Instanz) deklariert hat M. Die Diskussion von Color Colornur zeigt, dass die Kombination Color Color mit static Mund Mdas Problem verschlimmert. Also mach nicht die ursprüngliche Idiotie.
ToolmakerSteve
4

Ein anderes Gotcha ist mit inneren Typen.

Ich treffe diesen die ganze Zeit:

public class Car {
    public enum Make {
        Chevy,
        Ford
    };

    // No good, need to pull Make out of the class or create
    // a name that isn't exactly what you want
    public Make Make {
        get; set;
    }
}
Chris
quelle
5
Deshalb pluralisiere ich meine Aufzählungsnamen. Es gibt mehrere mögliche MakesAutos, aber dieses Auto hat nur eines Make. Es liest sich nicht immer am besten, aber ich sehe es als Aufzählung, die eine Liste von möglichen ist Makes.
Hand-E-Food
3

Es gibt kein spezifisches technisches Problem damit. Dies kann die Lesbarkeit beeinträchtigen oder verbessern. In der Tat haben einige Microsoft-Bibliotheken diese Art von Eigenschaften (insbesondere bei enumEigenschaften ist dies normalerweise sinnvoll).

mmx
quelle
2

Dieses allgemeine Muster ist einer der Gründe, warum ich es immer verwende, thiswenn ich auf ein Instanzmitglied innerhalb einer Klasse verweise. zB immer

this.SomeMethod(this.SomeProperty);

und niemals

SomeMethod(SomeProperty);

In den meisten Fällen gibt es keine tatsächliche Mehrdeutigkeit, aber ich finde, es hilft, die Dinge zu klären. Außerdem wissen Sie jetzt, wo die Eigenschaft / Methode definiert ist.

Annabelle
quelle
1

Es kann natürlich etwas verwirrend sein, wenn der Name einer Eigenschaft und ihr Typ identisch sind, aber ansonsten ist es kein wirkliches Problem.

Wenn der Name Sinn macht, ist es normalerweise besser, den Namen und den Typ gleich zu lassen. Wenn Sie sich einen besseren Namen vorstellen können, sollten Sie diesen natürlich verwenden, aber Sie sollten nicht versuchen, um jeden Preis einen Namen zu finden, nur um diese Situation zu vermeiden.

Guffa
quelle
0

Ich gebe den Dingen den gleichen Namen wie ihrem Typ, außer in Groß- und Kleinschreibung: Meine Methoden und Eigenschaften sind "lowerCase"; und ich hätte daher nicht das Problem, das MiffTheFox hat.

public class B1
{
    public static void myFunc(){ ; }
}

public class B2
{
    private B1 m_b1;

    public B1 b1
    {
        get { return m_b1; }
        set { m_b1 = value; }
    }

    public void Foo()
    {
        B1.myFunc(); //this is Ok, no need to use namespace
    }
}

Für mich sind m_b1also Mitgliedsdaten, b1eine Eigenschaft (oder eine lokale Variable oder ein Parameter) und B1der Name der Klasse.

ChrisW
quelle
5
Leider steht die Verwendung von Kleinbuchstaben für Eigenschaften und Methoden in direktem Widerspruch zu den akzeptierten Benennungsrichtlinien für C #.
Timothy Walters
Ja. Das sind minderwertige Richtlinien, IMO, stimmst du nicht zu? Warum sind sie gekommen?
ChrisW
1
Es ist ein Kompromiss, der die Klarheit maximiert / Missverständnisse minimiert. Betrachten Sie eine typische Codedatei von Ihnen. Zählen Sie alle Auftritte aller Klassennamen, Mitgliedsnamen und lokalen Variablennamen. Sie werden feststellen, dass Klassennamen einen kleinen Bruchteil des gesamten Auftretens benannter Elemente ausmachen. Ihre Wahl weist also einer großen Mehrheit der Namensauftritte "Kleinbuchstaben" zu. Daher weisen Sie der Unterscheidung von "Klasse" von "Nichtklasse" einen hohen Wert zu. Daran ist nichts auszusetzen, aber der empfohlene Stil unterscheidet stattdessen "lokal" von "nicht lokal". Vielleicht in umgekehrter Weise aus dem Gleichgewicht
geraten