C#:一个被低估的"现代化程度最高的主流语言"
为什么它常被低估
C# 在中文技术圈的存在感长期偏低,原因是它和 Windows、.NET 深度绑定,早年又被视作"Java 的山寨版"。但如果把偏见放一边,只看语言设计本身,2026 年的 C# 可能是主流语言里语法演进最激进、同时工程质量把控最好的那一个。
几个事实:
- 它是第一个大规模使用"编译期可空引用检查"的主流语言(C# 8,2019 年)。
- 它比 Java 早十多年支持
async/await(2012 年,Rust 到 2018 才有)。 - 它的模式匹配、
record、init属性,比同期的 Java 版本早。 - .NET 从 2016 年 CoreCLR 开始跨平台,现在 Linux 上的部署量不比 Windows 少。
时间线
- 2000:Anders Hejlsberg 主导(就是后来去做 TypeScript 的那位),最初叫 Cool,后改名 C#。当时的定位是"给 .NET 平台设计的语言"。
- 2002:.NET Framework 1.0 + C# 1.0,有托管代码、JIT、GC。和 Java 的差别在于它一开始就有值类型(
struct)。 - 2005:C# 2.0 加泛型——注意,这是真正的运行时泛型,不是类型擦除。
List<int>在运行时就是List<int>,没有装箱。 - 2012:C# 5 加
async/await。这次影响深远,后面所有语言都在抄这套设计。 - 2016:.NET Core 发布,跨平台 + 开源。这是分水岭。
- 2020:C# 8 加可空引用类型、
switch表达式、using声明。 - 2022:C# 11 加原始字符串、列表模式、required 成员。
- 2023-2025:C# 12/13/14 持续加主构造器、集合表达式、
params集合、field 关键字、扩展成员等。
语言特性:真正好用的几块
1. 值类型与引用类型,区分得很清楚
public struct Point { public double X, Y; } // 栈上/内联,无 GC 压力
public class Node { public double X, Y; } // 堆上,引用语义
var p1 = new Point { X = 1, Y = 2 };
var p2 = p1; // 值拷贝,互不影响
var n1 = new Node { X = 1, Y = 2 };
var n2 = n1; // 同一对象
Java 只有基本类型和对象,无法自定义"值语义的结构体";C# 的 struct 能让你在需要高性能的场景(向量、坐标、小记录)避免堆分配。这也是它在游戏(Unity 用它做脚本层)和高性能库上有一席之地的原因。
2. 可空引用类型:把空指针变成编译期问题
#nullable enable
public string? FindName(int id) // 返回可能为 null,调用方必须处理
{
return id > 0 ? Lookup(id) : null;
}
var name = FindName(3);
Console.WriteLine(name.Length); // ⚠️ 编译警告:可能为 null
if (name is not null)
Console.WriteLine(name.Length); // ✅ 编译器确认已判空
这是现代 C# 最重要的一条工程能力。它不像 TS 那样"类型只是注解",而是在整个代码库里强制区分 string 和 string?,且对现有代码可以不开启(渐进迁移)。配合 not null 约束和 required 成员,能在较大程度上把"空引用异常"这类问题前置。
3. 模式匹配:表达力非常强
public abstract record Shape;
public record Circle(double R) : Shape;
public record Rect(double W, double H) : Shape;
static double Area(Shape s) => s switch
{
Circle { R: var r } => Math.PI * r * r,
Rect { W: var w, H: var h } => w * h,
_ => throw new ArgumentException("unknown shape")
};
配合 record(自动生成相等性、ToString、不可变 init 属性)和 with 表达式,C# 在"数据建模"这块的书写体验比 Java 的 record 更成熟:
var order = new Order { Id = 1, Amount = 199m, Status = OrderStatus.Paid };
var shipped = order with { Status = OrderStatus.Shifted }; // 复制并改一个字段
4. async/await:这套设计的原型
public async Task<string> FetchAsync(HttpClient client, string url)
{
using var resp = await client.GetAsync(url);
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
var results = await Task.WhenAll(urls.Select(u => FetchAsync(client, u))); // 并发
C# 的 async 是编译器生成状态机,不是回调也不是线程。同步与异步的代码看起来完全一样,这是它相比 Go(goroutine + channel)在"写法自然度"上的优势,也是 Rust 生态至今还在为 async 的可用性做斗争的原因。
运行时:.NET 现在是什么
.NET Core 之后,架构清晰:
- CLR:JIT(RyuJIT)编译 + GC(分代,有 Server GC / Workstation GC 模式)。
- AOT:Native AOT(2022 后成熟)可以直接编译成本机二进制,启动毫秒级、无需运行时。这让 .NET 终于能进 Serverless 和 CLI 场景。
- 跨平台:Windows / Linux / macOS,官方 Docker 镜像齐全。
- 性能:从 .NET 5 开始做了多年专项优化,官方 benchmark 显示在 JSON 序列化、Kestrel HTTP 服务等场景已经和 Go、Node 处于同一梯队,部分指标领先。
一段性能相关的实用配置:
# 容器内跑 Node/Go 类服务时的典型调优
DOTNET_gcServer=1 # 使用 Server GC,多核吞吐更好
DOTNET_TieredPGO=1 # 分层编译 + 配置文件引导优化
DOTNET_TC_QuickJitForLoops=1
部署形态:
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY *.csproj ./
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -r linux-x64 --self-contained false -o /out
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY /out .
ENTRYPOINT ["dotnet", "app.dll"]
生态:强项与弱项
强项:
- ASP.NET Core:性能一流的 Web 框架,Minimal API 写法和 Go 的
net/http一样简单。 - Entity Framework Core:成熟的 ORM,迁移工具完善。
- Blazor:用 C# 写前端(WebAssembly),适合团队只有 C# 能力的场景。
- Unity:游戏脚本层事实标准。
- 桌面:MAUI、WPF(Windows)、Avalonia(跨平台,社区活跃)。
- 工具链:Visual Studio 的调试、诊断、性能分析体验是第一梯队,
dotnetCLI 也够用。
弱项:
- 机器学习:ML.NET 能用,但和 Python 生态完全不在一个量级。
- 前端原生的 Web 生态:Blazor 做得不错,但主流仍是 JS/TS。
- Linux 运维圈的接受度:比 Go 低。很多运维工程师看到 .NET 会先皱眉(这是历史包袱,不是技术问题)。
- 第三方库数量:NuGet 的规模不如 npm/PyPI,冷门领域容易找不到。
判断标准
选 C#:企业级后端(尤其已有 Windows 系基础设施)、需要强类型 + 良好异步的大型服务、桌面应用、Unity 游戏、团队有 C#/VB 存量、需要 Native AOT 的轻量服务。
不选 C#:纯 Linux 原生云原生栈(Go 更符合生态习惯)、机器学习与数据科学(Python)、对二进制体积极度敏感(Go 的静态单文件更省心)、社区必须完全开源无商业背景的项目。
一个视角
如果你的技术视野只停在"Java、Python、JS、Go",那 C# 会被系统性地忽略。但它其实提供了一个非常完整的对照组:同样是强类型、同样有 GC、同样面向企业,它选择了比 Java 更激进的演进路线。许多后来被 Java、Rust、Kotlin 采用的设计(可空检查、模式匹配、record、async),C# 要么先做,要么做得更彻底。看它一眼,能校准你对"什么才是现代语言"的判断。