当前位置:网站首页>. Net C # Foundation (6): namespace - a sharp tool for organizing code

. Net C # Foundation (6): namespace - a sharp tool for organizing code

2022-06-09 09:00:00 HiroMuraki

0. The purpose of the article

   oriented C# New scholar , Introduce namespaces (namespace) And C# Namespace in

 

1. Fundamentals of reading

   understand C And C# The basic grammar of language

 

2. Name conflicts with namespace

2.1 An example of life

   Suppose cat head has a name in Beijing AAA Friend, , There are two in Shanghai called AAA Friend, , Two in Shanghai AAA One likes salty rice dumplings , One likes sweet dumplings . One day, cat cat played with her friends , Asked the friend :

  “AAA How is everything going recently? ”,

   However, the cat has three names AAA Friend, , So cat cat is not sure what his friend is asking AAA, So the friend asked :

  “ The one in Shanghai AAA How is everything going recently? ”

   A little more precise , But that's not enough , Because cat and cat head met two people in Shanghai AAA Friend, , So the friend asked again :

  “ The one in Shanghai likes salty zongzi AAA How is everything going recently? .

   Come here , Maomaotou decides which Xiao Ming his friend asked . in other words , By Region + like + full name , A cat's head can determine who a friend refers to .

   This example shows the essence of namespaces : Restrictive modification .

2.2 from C Language defects to namespaces

(1) Function naming conflict

   Before we talk about namespaces , Let's take a look first C Some problems in language . Suppose you and your partner develop a C Program , And you happen to define two functions with the same function name :

void Init() { }

void Init() { }

   Suppose the two functions do completely different things ( One to initialize the console , One to initialize the printer ) And cannot merge , So it is obvious that there is a way to distinguish the two functions . After a brief discussion , You and your friends decide to add the function object name before each function name to distinguish , So you changed the function name to the following :

void ConsoleInit() { } //  For initializing the console Init

void PrinterInit() { } //  Used to initialize the printer Init

   With the development progress , You may create more and more functions with the same name , Finally, the function name will likely look like the following :

void ConsoleInit() { }
void ConsoleFoo() { }
void ConsoleWhatever() { }
void ConsolePrint(const char* s) { }
...

void PrinterInit() { }
void PrinterFoo() { }
void PrinterWhatever() { }
void PrinterPrint(const char* s) { }
...

   Of course, such function names are not bad , But the function name contains unnecessary redundant information , Using this function name makes the code less readable , what's more , This will also greatly increase the number of characters that need to be entered when writing code :

ConsoleInit();
ConsoleFoo();
ConsoleWhatever();
ConsolePrint("...");

   In the above example , All the functions you need to use have been added Console Prefix , Even at this time, you can know that you are operating the console most of the time , Whether using or reading , These prefixes are just superfluous for you . On the other hand , Suppose there is a way for the compiler to automatically add the names of all functions used in a certain range ‘Console’ Prefix , You can do something like this :

//  Tell the compiler to add... To the following function names Console Prefix 

Init();
Foo();
Whatever();
Print("...");

   Obviously, it is much easier to use functions at this time .

(2) Let the compiler do it for you

   For the above reasons , You can define a syntax that tells the compiler to add the specified prefix to the function names used next , for example :

using Console; //  Tell the compiler to add... For all the next functions Console Prefix 

Init();
Foo();
Whatever();
Print("...");

   ad locum , We set to use using Keyword to tell the compiler to add... To all functions Console Prefix , So in the compiler's view , The actual code above is as follows :

ConsoleInit();
ConsoleFoo();
ConsoleWhatever();
ConsolePrint("...");

   Obviously, at this time, the program can still accurately call the appropriate function .

(2) Further more

   Since you can let the compiler automatically prefix a function when it is called , So why not let the compiler automatically prefix function names when we define functions ? therefore , You can also define a syntax that tells the compiler to automatically prefix the function names of defined functions , ad locum , Let's suppose we use namespace( You will soon know why ) Keyword indicates the prefix that needs to be added , And let the compiler add the required prefix to all the functions defined in the subsequent code block , It's like this :

namespace Console //  Add... Before the function defined in the following code block Console
{
    void Init() { }
    void Foo() { }
    void Whatever() { }
    void Print(const char* s) { }
}

   Now we specify that the above syntax is equivalent to telling the compiler : Automatically add... At compile time for all functions defined in the code block Console Prefix , So after the compiler performs automatic conversion , The above code will look like the following :

void ConsoleInit() { }
void ConsoleFoo() { }
void ConsoleWhatever() { }
void ConsolePrint(const char* s) { }

   Use this grammar , Defining a function like this not only simplifies the function name , At the same time, potential function name conflicts can be avoided :

namespace Console //  Tell the compiler to add... For all defined functions in subsequent code blocks Console Prefix 
{
    void Init() { }
    // ...
}

namespace Printer //  Tell the compiler to add... For all defined functions in subsequent code blocks Printer Prefix 
{
    void Init() { }
    // ...
}

   Even closer to , You can add prefixes using nested syntax :

namespace MeAndFriend
{
    namespace Console //  Tell the compiler to add... For all functions in the code block Console Prefix 
    {
        void Init() { }
        // ... 
    }

    namespace Printer //  Tell the compiler to add... For all functions in the code block Printer Prefix 
    {
        void Init() { }
        // ...
    }
}

   For example, the above code will be generated by the compiler into something like ‘MeAndFriendConsoleInit’ And ‘MeAndFriendPrinterInit’ Such function names . Obviously, this syntax greatly reduces the amount of input required , And combine with the previous using grammar , It is also convenient to call :

using MeAndFriendConsole; //  Tell the compiler that all the next functions have... By default MeAndFriendConsole Prefix 

Init();
... //  Others also need MeAndFriendConsole Function of prefix 

2.3 Namespace

   Those mentioned in the above example are so-called automatic by the compiler ‘ Prefix ’, We can give it a nice name : Namespace (namepsace), Or you can call it a namespace / Namespace . It can be seen from the above examples that , A namespace is actually a qualified decoration used to precisely locate specific members . Namespaces are not really necessary , For example, if it is to avoid function name conflicts , You can avoid conflicts by adding various qualifiers to function names , However, as we have seen before , If every function needs to input so much additional information unrelated to what the function does when it is defined and called , So typing and reading code is an extra burden , And it may bring a lot of inconvenience to possible code modification in the future , The emergence of namespaces and related syntax support have greatly slowed down this problem .

 

3. C# The namespace in

   Namespaces are such useful things , So many modern programming languages have namespace like designs .C# Naturally, it has its own namespace system ,MSDN The namespace is defined on ‘ A scope that contains a set of related objects ’, This concept is a bit abstract , Next, we will understand from the specific use .

3.1 Use

3.1.1 Declare a namespace :namespace keyword

(1) Base namespace

   To be in C# Declare a namespace in , Just use namespace Keyword plus the name of the namespace and a pair of curly braces ( Code block ) that will do :

namespace Alpha
{
    
}

   The types defined in the code block of the namespace will be regarded as the types belonging to the namespace , for example :

namespace Alpha
{
    class Foo
    {

    }
}

   The above code declares a namespace Alpha, And in Alpha Define a Foo object . In the practical sense of namespaces , If you use a period . To connect namespace and type name , that Foo The full name of the type is Alpha.Program. Use namespace , You can define the same type name like this without conflicts :

namespace Alpha
{
    class Foo
    {

    }
}

namespace Beta
{
    class Foo
    {

    }
}

   Although there are two names in the above code Foo Class , But the full type names of the two are Alpha.Foo And Beta.Foo, From the point of view of the program, these are two completely different types . The compiler will replace the type name with the full type name at compile time ( Namespace + Combination of type names ), Therefore, the program runtime can accurately locate specific types without confusion .

   For the convenience of the following description , We will ‘ With The full name of the namespace to which it belongs . Type name Type name of format expression ’ be called ‘ Full type name ’.

(2) Nested namespace

   You can nest declared namespaces :

namespace Alpha
{
    namespace Beta
    {
        class Program
        {   

        }
    }
}

   At this point, the... In the above code Program The full type name of the type is Alpha.Beta.Program. However, nested namespaces waste a lot of column indentation ( According to the format specification , The code in each level of code block needs to be indented 4 A space , So every extra layer of namespaces causes all code to be indented more 4 A space ), So you can also use a period . To connect namespaces to represent nested relationships of namespaces , For the nesting of the above namespaces, you can also use the following declaration method :

namespace Alpha.Beta
{
    class Program
    {   

    }
}

   Then Conceptually speaking ,Alpha Is the root space , and Beta It is Alpha The subspace of . Besides , All namespaces have a common root space , It is called the global namespace , It is implicit and anonymous , The contents under the global namespace can be accessed directly without adding additional restrictions . for example , Here is a class in the global namespace :

class Foo
{

}

   If you need to use this Foo Type can use its type name directly ‘Foo’, There is no need to add additional restrictions ( Provided that it does not conflict with the namespace type name in which it is used , If the conflict requires additional qualification , It will be mentioned later ). Simply put, it can be seen as Foo The type has no namespace to which it belongs , But conceptually , type Foo Still belong to a namespace , But the namespace is implicit and anonymous .

3.1.2 using namespace std :using keyword

(1)using Instructions

   Types in the same namespace can be accessed directly by using their type names , For example, for the following type definitions :

namespace Alpha
{
    class Foo { }
}

   type Foo The full type name of is Alpha.Foo, But in Alpha Namespace Foo You can use its type name directly when typing ‘Foo’:

namespace Alpha
{
    class Foo { }

    class Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo();
        }
    }
}

   This rule also applies to its subspace :

namespace Alpha
{
    class Foo { }  //  Defined as Alpha Under space Foo type 

    namespace Beta // Beta yes Alpha The subspace of 
    {
        class Program
        {
            static void Main(string[] args)
            {
                Foo foo = new Foo();  //  You can also directly use the class name to indicate the type 
            }
        }
    }
}

   On the other hand , If the namespace wants to use the types defined in its subspace , You can use the subspace name . Type name access , That is, it is equivalent to using the target type from this namespace , for example :

namespace Alpha
{
    namespace Beta     // Beta yes Alpha Nested namespace of 
    {
        class Cat { }  //  It's defined in Alpha.Beta Under the Cat class 
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Beta.Cat cat = new Beta.Cat(); //  Use the subspace name + Type name specifies the type 
        }
    }
}

   However , If you want to use in other namespaces Alpha Under the namespace Foo, You need to use its full type name Alpha.Foo, For example, in Test Namespace Alpha.Foo:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Alpha.Foo foo = new Alpha.Foo(); //  Use the full type name 
        }
    }
}

   Obviously, using full type names is a tedious task ,C# Nature provides a corresponding solution . If you want to be like Alpha Just as simple to use directly in a namespace Foo, have access to using Instructions :

using Alpha; // using Instructions , Import Alpha Namespace 

namespace Beta
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo1 = GetFoo();
        }
        static Foo GetFoo() { ... }
        static void CheckFoo(Foo foo) { ... }
    }
}

   stay using Keyword followed by namespace name , You can set the specified namespace ‘ Import ’ In this document . So-called ‘ Import ’ Is to tell the compiler if the type name appears in the code , Then, in addition to searching for types in the scope of this namespace , It can also be done by using Instruction to search the imported namespace range . When the compiler finds the specified type, it will replace the type name with its full type name . in other words , Aforementioned using Alpha The directive tells the compiler that it can Alpha Namespace to find the type , So when the compiler finds Main Methodical Foo Type is not in Beta Namespace , From Alpha Namespace , stay Alpha Next discovery Foo after , Compiler will Main Medium Foo Replace with its full type name Alpha.Foo. Therefore, the above code is equivalent to removing using Command and send all Foo Replace with Alpha.Foo Compiled results of .

   in addition , Multiple can be used at the same time using Statement to import multiple namespaces , also using The order of does not affect program behavior , There will be no such thing ‘ Back using Namespace overrides the front using Types with the same name in the namespace of ’ The problem of . in addition , The same using The instruction can repeat the declaration , Although in practice, this behavior is meaningless . therefore , The following using The effect of the declaration is consistent :

// 1.  First Alpha Again Beta
using Alpha;
using Beta;

// 2.  First Beta Again Alpha
using Beta;
using Alpha;

// 3.  Reuse the same using Instructions , feasible , But it doesn't make sense , The compiler will warn 
using Alpha;
using Alpha;
using Beta;
using Beta;
using Beta;

   In terms of actual behavior ,using The directive simply tells the compiler if a type name appears in the code , Then, in addition to finding the corresponding type within this namespace , It can also be done by using Directive to search within the imported namespace .using The scope of the directive is the file scope , That is to say a using The instruction pair uses this using The entire document of the directive is valid , For this reason ,using Instructions are required to be placed at the beginning of the file to clearly describe their behavior .

(2)using Alias

   You can use using Define an alias for the type :

using Alias = Alpha.Foo;

Alias foo = new Alias(); //  Equate to Alpha.Foo foo = new Alpha.Foo()

   By using using < Alias > = < Full type name >, You can specify an alias for the specified type , This alias can be used in subsequent code to refer to the type , For example, the above code is Alpha.Foo Type specifies an alias Alias, The compiler encountered a use in the code Alias Type will be replaced by Alpha.Foo. in addition ,using Aliases also apply to generics :

using CatList = System.Collections.Generic.List<Cat>;

CatList cats = new CatList(); 

  using The alias scope is also the entire file , So for the same reason ,using The alias declaration is also required at the beginning of the file .

3.1.3 global keyword

   By default , The compiler will take the current namespace as the starting point when obtaining the search type :

class Foo { }     //  Located in the global namespace Foo

namespace Alpha
{
    class Foo { } //  In namespace Alpha Of Foo

    class Program //  In namespace Alpha Of Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo(); //  At this time Foo yes Alpha.Foo, Because the compiler takes priority to find from the current namespace 
        }
    }
}

   In the above code Main Methods Foo yes Alpha.Foo, The reason is that the compiler starts with a namespace Alpha Find... For the starting point ‘Foo’ I found that Foo Type definition of , Therefore, we will not look for the in the global namespace Foo. At this point, if you want to use... In the global namespace Foo, You need to tell the compiler to start searching from the global namespace ( Instead of the current namespace ), You can add... Before the type name by global:: To achieve this :

global::Foo foo = new global::Foo(); //  Tell the compiler to start searching from the global namespace , here Foo The one in the global namespace Foo

   It can be said that ,global Is the global namespace ‘ name ’, It just needs to be followed by :: instead of .( Yes C++ My friends may be quite familiar with this grammar ). in addition , Can combine global And using Directive to import global namespaces , This will be mentioned later .

3.2 Namespace conflict

(1) The imported namespace has a type name conflict with the current namespace

   Sometimes the imported namespace may contain type names that conflict with the current namespace , for example :

   file 1 Content :

namespace Alpha
{
    class Foo { }
}

   file 2 Content :

using Alpha;

namespace Test
{
    class Foo { }
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo(); // Alpha.Foo still Test.Foo?
        }
    }
}

   file 1 Medium Alpha Namespace defines a Foo object , file 2 Use in using The instruction imports Alpha Namespace , But at the same time in its namespace Test It also defines a Foo, also Main Method is not a full type name , Which one should the above code use Foo? The answer is Test.Foo, That is, under this namespace Foo. The reason is mentioned earlier , When the compiler gets a type, it will take the current namespace as the starting point to search , Only if it cannot be found under the current namespace will it be found from the imported namespace . therefore , If you want to use Alpha Under the Foo, It still needs to use the full type name :

Alpha.Foo foo = new Alpha.Foo();

   Note that this time using Invalid alias , The same reason is that the compiler will take the current namespace as the starting point when obtaining types , This is more than using Alias has high priority .

(2) There is a type name conflict between imported namespaces

   Multiple using Type name conflicts may also occur between namespaces imported by directives , For example, the contents of the two files are as follows :

   file 1 Content :

namespace Alpha
{
    class Foo { }
    class Cat { }
}

namespace Beta
{
    class Foo { }
    class Dog { }
}

   file 2 Content :

using Alpha;
using Beta;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Cat cat = new Cat(); //  yes Alpha.Cat
            Dog dog = new Dog(); //  yes Beta.Dog
            Foo foo = new Foo(); // Alpha.Foo still Beta.Foo?
        }
    }
}

   file 2 Using two using Instructions are imported into Alpha On Beta Namespace , And in Main Methods use types under these two namespaces . among Cat Only in Alpha Namespace has been defined , So you can confirm its full type name , Empathy Dog It's fine too . However, due to the Alpha and Beta At the same time, it defines Foo type , also using The order of does not affect program behavior , Therefore, the compiler cannot confirm Foo In the end should use Alpha still Beta Namespace . To solve this kind of problem , You also need to use the full type name :

Alpha.Foo foo = new Alpha.Foo();
Beta.Foo foo = new Beta.Foo();

   Of course , You can also use using Alias to specify Foo Type represented :

using Foo = Alpha.Foo; //  take Foo As Alpha.Foo Another name for 
using Foo = Beta.Foo;  //  Or will Foo As Beta.Foo Another name for 

3.3 Special namespaces

3.3.1 static Namespace

  static Namespaces are used to simplify member calls to static classes . For example, there are the following static classes :

namespace Hello
{
    static class Speaker 
    {
        public static void Say();
    }
}

   Use this static class in another file :

using Hello;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Speaker.Say();
            Speaker.Say();
            Speaker.Say();
        }
    }
}

   There is no problem with the above usage , But static classes don't need to be instantiated , And static classes are often just used to organize code . let me put it another way , Sometimes the class name of a static class is not important , It can be omitted . So ,C# Provides a special using Directive allows programmers to omit the class name when calling static class members :

using static Hello.Speaker; // using static +  The full type name of the static class 

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Say();
            Say();
            Say();
        }
    }
}

   The above code uses using static + The full type name of the static class Import static classes to the current file , Tell the compiler to use the method or field in the next code if the definition is not found in this type , Can be found from the members of the imported static class . therefore , above Main Method call Say When the method is used , Compiler found Program Type has not been defined Say Method , So try to use using static Imported Hello.Speaker Find a static class named Say Methods .

3.3.2 Namespaces that act on file scope

   The scope of a normal namespace declaration is the code block behind it , But you can also declare namespaces that apply to the entire file range , After declaration, all types defined under this file will be included in this namespace :

namespace Alpha; //  take Alpha Namespace declared as file scope 

class Cat { }
class Dog { }

   Declaring a file scoped namespace is similar to the namespace syntax of a scoped code block , Its biggest advantage is that it reduces the amount of column indentation required when formatting code styles . It should be noted that , Declaring namespaces that act on file scopes has the following restrictions :

  1. File scoped namespaces can only be declared once , It's obvious
  2. You can no longer declare a common namespace , in other words , The following code is invalid ,Beta It will not be regarded as Alpha The subspace of :
namespace Alpha;

namespace Beta
{

}

3.3.3 Global namespace

   default using The directive scope is a file , That is to say a using The declaration of the directive only applies to the using This file of the directive is valid . But sometimes a namespace may be frequently used for multiple files , for example System Namespaces are quite common , Many files need to be added additionally using System To import this namespace , This can sometimes lead to a boring experience for coding , So ,C# Provides a method called global using How to import , according to this using The imported namespace will be applied to the entire project , Only need using Add... Before the command global Keyword to import a namespace as a global namespace :

global using System;

   Use the above... In any file in a project using After declaration , All files in the project will be imported by default System Namespace . in addition , The syntax defines the overall situation using Must be in normal using Before , Therefore, it is suggested that the overall situation using Write to a single file .

 

4. Namespace gossip

4.1 The process of finding the complete type name

   The compiler looks for the types in the following stream order :

  ( In the above process , If the desired type is found in a blue block, it will jump out , Otherwise, go to the next blue block in the order of the arrow to find )

   There is no need to memorize the process , The main significance of the above process is to explain some behaviors of namespaces . It doesn't mean much in itself , The actual code is written according to IDE Tips and running results can easily solve relevant problems .

4.2 Namespace “ name ”

  MSDN Namespace is given on Naming suggestions

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

  1. Add the company name or personal name before the namespace name .
  2. Use stable at the second level of namespace names 、 Version independent product names .
  3. Use Pascal nomenclature , And use a period to separate namespace components . however , If the brand name has its own case rules , Follow the brand name .
  4. Use plural namespace names where appropriate , Exceptions to acronyms .
  5. The namespace should not be the same as the type name within its scope ( For example, it should not be in the namespace Foo define Foo type ).

   Example :

namespace Microsoft.Office.PowerPoint { }

4.3 namespace And using Location

  C# To use namespace And using There are some requirements for the position where the statement appears , Usually a possible order is as follows :

global using System; //  overall situation using Instructions 

namespace Alpha;     //  Namespaces that act on file scope 

using Alpha;         // using Instructions 

using IntList = System.Collections.Generic.List<int>; // using Alias 

namespace Beta       //  Common namespace 
{

}

   The specific order does not need to be memorized , If the order does not meet the requirements, the compiler will give a prompt .

4.4 Fully qualified namespace

   The namespace represented by the global namespace as the root space is called ‘ Fully qualified namespace ’, For example, for the following namespace :

namespace A
{
    namespace B
    {
        namespace C
        {
            
        }
    }
}

   If you want to represent the namespace under the above namespace declaration C, have access to A.B.C, But if you are in a namespace A in , You can also use B.C, But only A.B.C This representation is the fully qualified namespace of the representation . By fully qualifying the namespace, you can accurately locate a namespace from the global namespace .

4.5 Implicit global namespace import

   Now new C# After the project , You will find the project csproj There is such a line in the file :

<ImplicitUsings>enable</ImplicitUsings>

   When the project starts ImplicitUsings when , Its function is equivalent to introducing a file for global import of common namespaces for your project , In other words, it is equivalent to adding files with similar contents in your project :

global using System;
global using System.Collections.Generic;
...

   This function is applicable to the overall situation using Practical application of instructions , Refer to here , You can also define a file that imports your common namespaces globally , And add it to your project as needed .

4.6 myth

   Although in the first example of this article , We are C Language is hypothetical using The function of a sentence is ‘ See that all the following functions have a prefix ’,C# Namespaces in seem to behave exactly the same way . However , Just thinking so will make people mistakenly think that the following code can be compiled :

   file 1 Content :

namespace A.B
{
    class Foo { }
}

   file 2 Content :

using A;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            B.Foo foo = new B.Foo(); //  look B.Foo Adding using Of A. After prefix , Namely A.B.Foo 了 
        }
    }
}

   In the above documents 2 in , Use using Declaration imported namespace A, And then in Main Method B.Foo To express A.B.Foo type . However, this cannot be compiled , If this behavior permits , Then consider the following code :

   file 1 Content :

namespace A.B
{
    class Foo { }
}

namespace B
{
    class Foo { }
}

   file 2 Content :

using A;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            B.Foo foo = new B.Foo(); //  At this time foo yes B.Foo still A.B.Foo
        }
    }
}

   because Test There is no... Under the namespace B.Foo Matches for , So now the compiler will start from using Declare to find the type in the imported namespace . The problem is... At this time B.Foo In the end is as B.Foo The full type name of the , still A.B.Foo Partial type name of ? To avoid this confusing situation ,C# The above practice is not allowed . It can be said that , When you decide to add a namespace to the type name , And the namespace to which the type belongs is not a subspace of the current namespace , You can only use its full type name . If the namespace to which the type belongs is a subspace of the current namespace, you can use Subspace name . Type name To indicate the type :

namespace B
{
    class Foo
    {
        public void Tell() { }
    }
}



namespace A
{
    namespace B
    {
        class Foo { }
    }
    class Program
    {
        static void Main(string[] args)
        {
            B.Foo foo = new B.Foo(); // B.Foo The full type name of is A.B.Foo
            foo.Tell();
        } 
    }
}

   Because the compiler will take the current namespace as the starting point to find the type , In the above case, the compiler can start from the namespace A Look for B.Foo, Therefore, it will be preferred to use . If you want to use the full type name B.Foo The type of , Add and use global:: that will do .

4.7 Use advice

(1) Only one namespace should be declared in a file

(2) Avoid declaring namespaces nested whenever possible , Instead, use a period . Represents the nested relationship of namespaces :

namespace Alpha      //  Nested declaration namespace 
{
    namespace Beta
    {

    }
}

namespace Alpha.Beta //  Use . To represent namespace nesting relationships 
{

}

(3) Flexible use Using Alias to avoid unnecessary type definition and simplify type name

using IntList = System.Collections.Generic.List<int>; //  It means a Int list , But no additional type definitions , It also simplifies the type name 

(4) Specify the order of importing namespaces , For example, you can import by namespace name , Or follow the built-in library first → Third party Library → Sequence import of the current project, etc

原网站

版权声明
本文为[HiroMuraki]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/160/202206090842489998.html