C# 命名空间(Namespace)
声明、嵌套、`using` 别名、`global using`、以及程序集。
声明
namespace Shop.Models
{
class Product
{
public string Name { get; set; } = "";
}
}
namespace Shop.Services
{
class ProductService
{
public string Describe(Models.Product p) => "商品:" + p.Name;
}
}
var s = new Shop.Services.ProductService();
Console.WriteLine(s.Describe(new Shop.Models.Product { Name = "键盘" }));商品:键盘// 文件范围命名空间(C# 10+),整个文件都属于它
namespace Shop.Models;
class Order
{
public int Id { get; set; }
}
// 上面这个 Order 的全名是 Shop.Models.Order嵌套与全名
namespace A
{
namespace B
{
class C
{
public static string Name => "A.B.C";
}
}
}
// 两种写法等价
namespace A.B
{
class D { }
}
Console.WriteLine(A.B.C.Name);
Console.WriteLine(typeof(A.B.D).FullName);A.B.C
A.B.Dusing
using System.Text;
using System.Collections.Generic;
// 别名
using StrList = System.Collections.Generic.List<string>;
using Dict = System.Collections.Generic.Dictionary<string, int>;
// 静态导入(C# 6):直接用静态成员
using static System.Math;
using static System.Console;
var list = new StrList { "a", "b" };
var map = new Dict { ["x"] = 1 };
WriteLine(string.Join(",", list));
WriteLine(map["x"]);
WriteLine(Sqrt(16));
WriteLine(Max(3, 7));a,b
1
4
7With using static System.Math you write Sqrt(16) instead of Math.Sqrt(16). Great for math-heavy code, though it blurs what is local versus imported.
global using
// GlobalUsings.cs —— 全项目生效,不用每个文件重复写
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;
// 项目文件里开启隐式 using 后,上面这些大部分自动包含<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>ImplicitUsings adds System, System.Linq, System.Collections.Generic and friends automatically per project type. Put your own frequently used namespaces in GlobalUsings.cs.
命名空间 vs 程序集
| Concept | Nature | Unit |
|---|---|---|
| 命名空间 | 逻辑 | 避免重名,可跨程序集 |
| 程序集 | 物理 | 一个 .dll / .exe |
System.String lives in System.Runtime.dll while System.Linq.Enumerable lives in System.Linq.dll. One namespace can span assemblies and one assembly can hold many namespaces.
Com.MyCorp.Project.Module. It avoids collisions and shows ownership at a glance.声明
namespace Shop.Models
{
class Product
{
public string Name { get; set; } = "";
}
}
namespace Shop.Services
{
class ProductService
{
public string Describe(Models.Product p) => "商品:" + p.Name;
}
}
var s = new Shop.Services.ProductService();
Console.WriteLine(s.Describe(new Shop.Models.Product { Name = "键盘" }));商品:键盘// 文件范围命名空间(C# 10+),整个文件都属于它
namespace Shop.Models;
class Order
{
public int Id { get; set; }
}
// 上面这个 Order 的全名是 Shop.Models.Order嵌套与全名
namespace A
{
namespace B
{
class C
{
public static string Name => "A.B.C";
}
}
}
// 两种写法等价
namespace A.B
{
class D { }
}
Console.WriteLine(A.B.C.Name);
Console.WriteLine(typeof(A.B.D).FullName);A.B.C
A.B.Dusing
using System.Text;
using System.Collections.Generic;
// 别名
using StrList = System.Collections.Generic.List<string>;
using Dict = System.Collections.Generic.Dictionary<string, int>;
// 静态导入(C# 6):直接用静态成员
using static System.Math;
using static System.Console;
var list = new StrList { "a", "b" };
var map = new Dict { ["x"] = 1 };
WriteLine(string.Join(",", list));
WriteLine(map["x"]);
WriteLine(Sqrt(16));
WriteLine(Max(3, 7));a,b
1
4
7using static System.Math 之后可以直接写 Sqrt(16) 而不用 Math.Sqrt(16)。数学密集的代码用它可读性提升明显,但也容易让人分不清哪些是本地方法。
global using
// GlobalUsings.cs —— 全项目生效,不用每个文件重复写
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;
// 项目文件里开启隐式 using 后,上面这些大部分自动包含<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>ImplicitUsings 会按项目类型自动加上 System、System.Linq、System.Collections.Generic 等。业务项目里常用的自定义命名空间也放 GlobalUsings.cs。
命名空间 vs 程序集
| 概念 | 性质 | 单位 |
|---|---|---|
| 命名空间 | 逻辑 | 避免重名,可跨程序集 |
| 程序集 | 物理 | 一个 .dll / .exe |
System.String 在 System.Runtime.dll 里,但 System.Linq.Enumerable 在 System.Linq.dll 里。同一个命名空间可以横跨多个程序集,一个程序集也可以包含多个命名空间。
Com.MyCorp.Project.Module。这样不会和第三方库撞名,也一眼看出归属。