最短的 C# 程序

Console.WriteLine("Hello, World!");

就这一行。C# 9(2020)引入 top-level statements,省了千年来的 class Program { static void Main() {...} } 样板。

创建项目

dotnet new console -n MyApp
cd MyApp

生成的结构:

MyApp/
├── MyApp.csproj         项目文件
├── Program.cs           入口源码
└── obj/                 构建中间产物(gitignore)

MyApp.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RootNamespace>MyApp</RootNamespace>
  </PropertyGroup>
</Project>

ImplicitUsings 自动引入 System / System.IO / System.Linq 等常用命名空间——Program.cs 不用写 using

Nullable 启用可空引用类型检查——详见 第 18 篇

dotnet run
# Hello, World!

第一次跑会编译 + 跑;之后 dotnet build 单独编译、dotnet run 不修改时直接跑。

读命令行参数

// args 是 string[],top-level 自动注入
Console.WriteLine($"参数数量: {args.Length}");
foreach (var a in args) Console.WriteLine(a);
dotnet run -- hello world 42
# 参数数量: 3
# hello / world / 42

--dotnet 知道后面的参数交给程序。

老 Program.cs 风格

namespace MyApp;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello");
    }
}

也能用。top-level 是简化,对于教学和小工具用 top-level;对于大型项目用类风格也无可厚非。两者编译产物等价。

async Main

入口需要 await?top-level 直接 await:

using System.Net.Http;

var client = new HttpClient();
var html = await client.GetStringAsync("https://example.com");
Console.WriteLine(html.Substring(0, 200));

类风格里要:

static async Task Main(string[] args) { ... }

读输入

Console.Write("你叫什么?");
var name = Console.ReadLine();
Console.WriteLine($"Hello, {name}!");

Console.ReadLine() 返回 string?(可能 null,如 EOF)。

数字要解析:

Console.Write("你几岁?");
if (int.TryParse(Console.ReadLine(), out var age))
{
    Console.WriteLine($"你 {age} 岁");
}
else
{
    Console.WriteLine("不是数字");
}

多文件项目

加新文件 Utils.cs

namespace MyApp;

public static class Utils
{
    public static string Shout(string s) => s.ToUpper() + "!";
}

Program.cs

using MyApp;

Console.WriteLine(Utils.Shout("hello"));   // HELLO!

同目录所有 .cs 自动编译——不需要列在 .csproj 里。

调试

VSCode / VS / Rider 里按 F5。命令行用 dotnet run -c Debug(默认)vs -c Release

dotnet run -c Release    # 优化版

发布版本 第 20 篇 roadmap 末尾提。

现代 C# 项目里很少看到的东西

老教程会教,新代码很少用:

  • using System; 等 ——自动 implicit usings 帮你
  • class Program / Main —— top-level 替代
  • string str; 接着 str = "x"; —— 直接 string str = "x";var str = "x";
  • ArrayList / Hashtable —— 永远用泛型 List<T> / Dictionary<K,V>
  • Console.ReadLine() 后转大写 + 转 int 的多步 —— 用 int.TryParse

学到的应该是今天怎么写,不是 .NET Framework 时代的写法。

→ 下一篇 工程命令