2017-02-16 4 views
0

Ich habe einen Namespace in einem referenzierten Projekt, Project.Base, und jemand dachte, es wäre eine gute Idee, ihre eigene generische List-Klasse in diesem Namespace zu deklarieren.Warum werden Namespaces nicht intuitiv verwendet?

Jetzt habe ich eine Code-Datei, die aus beginnt:

using System.Collections.Generic; 
using Project.Base.Sub; 

Der Project.Base Namespace wird eigentlich nie offiziell verwendet wird; nur ein geschachtelter Namespace darin. System.Collections.Genericist formell verwendet. Aber aus irgendeinem seltsamen Grund, wenn ich eine Methode deklariere, deren Rückgabetyp List<T> ist, interpretiert sie das als anstatt als System.Collections.Generic.List<T>!

Dies scheint unglaublich kontraintuitiv zu mir. Weiß jemand, was vor sich geht und wie man es repariert?

EDIT zu reproduzieren:

using System; 
using System.Collections.Generic; 
using Project.Base.Sub; 

namespace Project.Base 
{ 
    public class List<T> { } 
} 

namespace Project.Base.Sub { } 

namespace Project.Base.Sub2 
{ 

    public class P 
    { 
     public static void Main() 
     { 
      var list = new List<int>(); 
      Console.WriteLine(list.GetType().Namespace); 
      Console.Read(); 
     } 
    } 
} 

(. Beachten Sie, dass der Code in Frage in einem anderen Unternamensraum von Project.Base ist Dies scheint bedeutend zu sein.)

+0

Konnten Sie den Code für den Namespace Project.Base.Sub veröffentlichen? Oder zumindest der Anfang –

+0

In welchem ​​Namensraum existiert der Code, der auf die 'List ' verweist? –

+2

'Namespace Project.Base { \t public class Liste {}} Namespace Project.Base.Sub {} Namespace Foo { \t System.Collections.Generic verwendet wird; \t mit Project.Base.Sub; \t \t public class P \t { \t \t public static void Main() \t \t { \t \t \t var list = new List (); \t \t \t System.Console.WriteLine (list.GetType(). Namespace); \t \t} \t} } 'Ihr Problem wie angegeben kann nicht reproduziert werden. ** Postleitzahl, die das Problem tatsächlich reproduziert **. –

Antwort

2

Namenssuche Erlös durch Durchsuchen von umschließenden Namespaces, und nur unter Berücksichtigung der using Direktiven, die in jedem Bereich sind.

Um diese Kompilierung zu machen, können Sie Ihre using Richtlinie innen bewegen kann:

using System; 

namespace Project.Base 
{ 
    public class List<T> { } 
} 

namespace Project.Base.Sub { } 

namespace Project.Base.Sub2 
{ 
    using System.Collections.Generic; 

    public class P 
    { 
     public static void Main() 
     { 
      var list = new List<int>(); 
      Console.WriteLine(list.GetType().Namespace); 
      Console.Read(); 
     } 
    } 
} 

Die Top-Level using Richtlinien sind nur innerhalb des globalen Namensraum, und würde so nur in einschließenden Namespace schlägt fehl, wenn Lookup durchsucht werden. So kann die erste Suche nicht finden Project.Base.Sub2.List, aber dann auf der nächsten Ebene, es befindet sich Project.Base.List. Wenn dies fehlgeschlagen wäre, hätte es versucht, einen Project.List Typ zu lokalisieren.

Die andere using Richtlinie war ein Ablenkungsmanöver.

2

Die akzeptierte Antwort ist korrekt. Eine andere Möglichkeit, das Problem zu verstehen ist, dass Ihr informiertes Code entspricht exakt

using System; 
using System.Collections.Generic; 
using Project.Base.Sub; 

namespace Project 
{ 
    namespace Base 
    { 
    public class List<T> { } 
    namespace Sub { } 
    namespace Sub2 
    { 
     public class P 
     { 
     public static void Main() 
     { 
      var list = new List<int>(); 
      Console.WriteLine(list.GetType().Namespace); 
      Console.Read(); 
     } 
     } 
    } 
    } 
} 

Und jetzt sollte klar sein, warum List löst, wie es der Fall ist. Die Deklaration von List befindet sich direkt in einem einschließenden Namespace.

Aus einer Design-Perspektive, wäre es eine gute Idee für Sie, auf Ihren Kollegen zurück zu drücken, der denkt, dass die Benennung einer Klasse "List" eine gute Idee ist. Es wird oft behauptet, dass Namespaces vorhanden sind, um Namenskonflikte zu verhindern, aber das ist eigentlich ihr sekundärer Zweck. Im realistischen Code gibt es normalerweise nicht sehr viele Benennungskonflikte, weil Leute im Allgemeinen Dinge wie Namen ihrer eigenen Klasse "List" nicht verwirren.

Der primäre Zweck der Namensräume ist zu Code in logische Gruppen organisieren, so dass Sie using verwenden können, um „in Umfang zu ziehen“ die Namen der Dinge, die Sie wahrscheinlich in Ihrem Programm verwenden. Dadurch kann IntelliSense besser herausfinden, was Sie beim Tippen meinen, den Code lesbarer macht und so weiter.Wenn Sie feststellen, dass Sie Namespaces verwenden, um Namenskonflikte zu vermeiden, sollten Sie überlegen, ob diese Konflikte durch einige taktische Umbenennungen behoben werden können.

+0

Ist das, was du gepostet hast, tatsächlich gültig? Ich hatte keine Ahnung, dass die C# -Sprache erlaubt, 'Namespace'-Blöcke zu verschachteln. (99,99% des Codes, den ich gesehen habe, verwendet einen 'Namespace' Block, um die gesamte Datei einzuschließen, mit der möglichen Ausnahme von Kommentarheadern und' using' Anweisungen, und der Rest ist entweder Tests oder Beispiele.) –

+1

@MasonWheeler: The Die C# -Spezifikation besagt eindeutig, dass 'der Namensraum Foo.Bar {}' * genau * der gleiche ist wie der 'Namensraum Foo {Namensraum Balken {}}'. Der Code ist gültig. Ich ermutige Sie, es auszuführen, wenn Sie Zweifel haben. Ich stelle fest, dass ich diesen Code nicht als * guten Stil * ansehen würde, aber er ist * gültig *. –

+0

@MasonWheeler: Wenn Sie mehr Fakten über Namespaces erfahren möchten, die Sie noch nicht kennen, sollten Sie https://blogs.msdn.microsoft.com/ericlippert/tag/namespaces/ –

Verwandte Themen