Ich habe einen C++-Hintergrund und verstehe die Antworten auf diese Frage vollkommen und stimme ihnen zu: Warum wird "using namespace std;" als schlechte Praxis angesehen?
Daher bin ich erstaunt, dass ich, nachdem ich nun einige Erfahrung mit C# gesammelt habe, dort das genaue Gegenteil sehe:
using Some.Namespace;
wird buchstäblich überall verwendet. Wann immer Sie einen Typ verwenden, fügen Sie zuerst eine using-Direktive für seinen Namespace hinzu (wenn er nicht schon vorhanden ist). Ich kann mich nicht erinnern, jemals eine .cs
-Datei gesehen zu haben, die nicht mit using System; using System.Collections.Generic; using X.Y.Z; etc...
begann.
Wenn Sie eine neue Datei über den Assistenten von Visual Studio hinzufügen, werden automatisch einige using-Direktiven hinzugefügt, auch wenn Sie sie vielleicht gar nicht benötigen. Während man also in der C++-Gemeinschaft im Grunde gelyncht wird, ermutigt C# sogar dazu, dies zu tun. Zumindest scheint es mir so zu sein.
Ich verstehe, dass die Verwendung von Direktiven in C# und C++ nicht genau dasselbe ist. Ich verstehe auch, dass eines der unangenehmsten Dinge, die man in C++ mit der Verwendung von Namespaces machen kann, nämlich sie in eine Header-Datei zu packen, in C# kein gleichwertiges Gegenstück hat, weil es kein Konzept für Header-Dateien und #include
gibt.
Trotz der Unterschiede dienen die Direktiven in C# und C++ dem gleichen Zweck, nämlich immer nur SomeType
zu tippen, statt des viel längeren Some.Namespace.SomeType
(in C++ mit ::
statt .
). Und mit demselben Zweck scheint mir auch die Gefahr dieselbe zu sein: Namenskollisionen.
Im besten Fall führt dies zu einem Kompilierungsfehler, so dass man ihn "nur" beheben muss. Im schlimmsten Fall wird der Code trotzdem kompiliert und tut stillschweigend etwas anderes, als Sie beabsichtigt haben. Meine Frage ist also: Warum wird die Verwendung von Direktiven in C# und C++ (anscheinend) als so ungleich schlecht angesehen?
Einige Ideen für eine Antwort, die ich habe (keine davon befriedigt mich allerdings wirklich):
Namensräume sind in C# tendenziell viel länger und viel mehr verschachtelt als in C++ (std
vs. System.Collection.Generic
). Es besteht also ein größerer Wunsch und ein größerer Gewinn, den Code auf diese Weise zu entrauschen. Aber selbst wenn das stimmt, gilt dieses Argument nur für die Standard-Namespaces. Benutzerdefinierte Namespaces können sowohl in C# als auch in C++ jeden beliebigen Kurznamen haben.
Namespaces scheinen in C# viel feinkörniger zu sein als in C++. In C++ ist zum Beispiel die gesamte Standardbibliothek in std
enthalten (plus einige winzige verschachtelte Namensräume wie chrono
), während in C# System.IO
, System.Threading
, System.Text
usw. vorhanden sind. Das Risiko von Namenskollisionen ist also geringer. Dies ist jedoch nur ein Bauchgefühl. Ich habe nicht wirklich gezählt, wie viele Namen Sie mit "using namespace std" und "using System" importieren. Und noch einmal: Selbst wenn dies wahr ist, gilt dieses Argument nur für die Standard-Namensräume. Eigene Namespaces können sowohl in C# als auch in C++ so feinkörnig gestaltet werden, wie Sie es wünschen.
Gibt es weitere Argumente? Ich bin vor allem an tatsächlichen harten Fakten interessiert (falls es welche gibt) und nicht so sehr an Meinungen.
Warum wird die Verwendung von "System;" nicht als schlechte Praxis angesehen?
"using System;" wird nicht allgemein als schlechte Praxis angesehen. Siehe zum Beispiel: Warum sollten Sie die 'using' Direktive in C# nicht verwenden?
Aber es mag wahr sein, dass es nicht als so schlecht angesehen wird wie die Verwendung des Namespace std. Wahrscheinlich weil:
C# hat keine Header-Dateien. Es ist unüblich, eine C#-Quelldatei mit Hilfe eines Präprozessors in eine andere einzubinden.
Der std
-Namensraum ist fast flach, d.h. fast alle Standardbibliotheksfunktionen, -typen und -variablen befinden sich darin (es gibt einige wenige Ausnahmen wie z.B. der Dateisystem-Sub-Namensraum). Er enthält eine sehr, sehr große Anzahl von Bezeichnern. Nach meinem Verständnis enthält System
viel weniger Namen und hat stattdessen mehr Unter-Namensräume.
In C# gibt es keine globalen Funktionen oder Variablen. Daher ist die Zahl der globalen Bezeichner im Gegensatz zu C++, wo es solche gibt, in der Regel recht gering: Darüber hinaus ist es typisch, C-Bibliotheken (oft indirekt) zu verwenden, die keine Namespaces haben, und daher alle ihre Namen in den globalen Namespace zu stellen.
Soweit ich weiß, hat C# kein argumentabhängiges Lookup. ADL in Verbindung mit dem Ausblenden von Namen, Überladen usw. kann dazu führen, dass einige Programme nicht von einem Namenskonflikt betroffen sind, während andere auf subtile Weise davon betroffen sind, und es ist nicht möglich, mit Tests alle Eckfälle zu erfassen.
Aufgrund dieser Unterschiede ist die Wahrscheinlichkeit eines Namenskonflikts bei "using System;" geringer als bei "using namespace std".
Außerdem ist der Namespace-Import in gewisser Weise eine sich selbst erhaltende Konvention: Wenn es konventionell ist, einen Standard-Namensraum zu importieren, dann werden Programmierer konventionell versuchen, Namen aus diesem Namensraum für ihre eigenen Bezeichner zu vermeiden, was dazu beiträgt, Probleme mit solchen Konventionen zu reduzieren.
Wenn ein solcher Import als schlechte Praxis angesehen wird, dann werden Programmierer weniger wahrscheinlich versuchen, Konflikte mit importierten Namensräumen zu vermeiden. Daher neigen Konventionen dazu, entweder für oder gegen die Praxis zu polarisieren, selbst wenn die Gewichtung der Argumente zwischen den beiden Optionen ursprünglich subtil war.
Die Verwendung von Direktiven in C# und C++ dient jedoch trotz ihrer Unterschiede demselben Zweck, nämlich immer nur SomeType eingeben zu müssen, statt des viel längeren Some.Namespace.SomeType (in C++ mit :: statt .). Und bei diesem gleichen Zweck scheint mir auch die Gefahr zu sein: Namenskollisionen.
Ja, aber Sie haben diese Gefahr nicht exportiert (sprich: andere dazu gezwungen, sich damit auseinanderzusetzen), weil:
Ich verstehe, dass die Verwendung von Direktiven in C# und C++ nicht genau dasselbe ist. Ich verstehe auch, dass eines der unangenehmsten Dinge, die man mit der Verwendung von Namespaces in C++ machen kann, nämlich sie in eine Header-Datei zu packen, in C# keine Entsprechung hat, weil es kein Konzept für Header-Dateien und #include gibt.
Es ist also eher eine andere Kategorie von Dingen.
Außerdem ist C++ nicht dafür ausgelegt, in einer IDE entwickelt zu werden, wie es bei C# der Fall ist. C# ist im Grunde immer in Visual Studio mit seiner Intellisense und was weiß ich geschrieben. Es ist so konzipiert, dass es auf diese Weise verwendet werden kann, von den Leuten, die es entwickelt haben. Unabhängig davon, wie viele Menschen eine IDE verwenden, um in C++ zu entwickeln, ist es nicht mit diesem Anwendungsfall als ein überwältigendes Anliegen konzipiert.
Namespaces scheinen in C# viel feinkörniger zu sein als in C++.
Ja, das auch. Namespace std verwenden" und "System.Collection.Generic verwenden" sind nicht vergleichbar.
Also vergleichen Sie sie nicht!