第一个 C# 程序
本章将带你创建并运行第一个 C# 程序,了解 C# 程序的基本结构,掌握编译和运行的基本流程。
Hello World 程序
创建项目
使用 Visual Studio 创建
- 启动 Visual Studio
- 选择"创建新项目"
- 选择"控制台应用"模板
- 配置项目信息:
项目名称:HelloWorld 位置:C:\CSharpProjects 解决方案名称:HelloWorld 框架:.NET 8.0
使用命令行创建
powershell
# 创建项目目录
mkdir HelloWorld
cd HelloWorld
# 创建控制台应用项目
dotnet new console
# 查看生成的文件
dir程序代码
Visual Studio 会自动生成以下代码:
csharp
// Program.cs
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}简化版本(.NET 6+ 顶级程序):
csharp
// Program.cs
Console.WriteLine("Hello World!");运行程序
在 Visual Studio 中运行
- 按 F5 键(调试模式运行)
- 或按 Ctrl+F5(不调试运行)
- 或点击工具栏的"开始"按钮
使用命令行运行
powershell
# 编译并运行
dotnet run
# 或者分步执行
dotnet build # 编译
dotnet bin/Debug/net8.0/HelloWorld.exe # 运行预期输出:
Hello World!C# 程序结构详解
传统程序结构
csharp
using System; // 1. 命名空间引用
using System.Collections.Generic;
namespace HelloWorld // 2. 命名空间声明
{
class Program // 3. 类声明
{
static void Main(string[] args) // 4. Main 方法
{
Console.WriteLine("Hello World!"); // 5. 程序语句
}
}
}结构组成说明
1. using 指令
csharp
using System; // 引入 System 命名空间
using System.IO; // 引入文件操作命名空间
using System.Collections.Generic; // 引入泛型集合命名空间
// 全局 using(C# 10+)
global using System;
global using System.Collections.Generic;作用:
- 引入命名空间,简化类型名称
- 避免写完整的类型名称
示例对比:
csharp
// 不使用 using
System.Console.WriteLine("Hello");
System.Collections.Generic.List<int> numbers;
// 使用 using
using System;
using System.Collections.Generic;
Console.WriteLine("Hello");
List<int> numbers;2. 命名空间 (Namespace)
csharp
namespace MyApplication
{
namespace Utilities
{
class Helper
{
// 类成员
}
}
}
// 嵌套命名空间简化语法(C# 10+)
namespace MyApplication.Utilities;
class Helper
{
// 类成员
}作用:
- 组织代码,避免命名冲突
- 提供逻辑分组
3. 类 (Class)
csharp
class Program // 类声明
{
// 类成员:字段、属性、方法等
}
public class Calculator // 公共类
{
// 类成员
}4. Main 方法
csharp
// 标准 Main 方法
static void Main(string[] args)
{
// 程序入口点
}
// 其他有效的 Main 方法签名
static void Main() // 无参数
static int Main(string[] args) // 返回整数
static int Main() // 无参数,返回整数
static async Task Main(string[] args) // 异步 Main(C# 7.1+)
static async Task<int> Main(string[] args) // 异步 Main 返回整数Main 方法特点:
- 程序的入口点
- 必须是 static
- 通常返回 void 或 int
- 参数 args 包含命令行参数
顶级程序 (Top-level Programs)
C# 9.0+ 简化语法
csharp
// 传统写法
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
// 顶级程序写法
using System;
Console.WriteLine("Hello World!");顶级程序特性
csharp
// 可以直接使用 args 参数
Console.WriteLine($"参数数量: {args.Length}");
foreach (string arg in args)
{
Console.WriteLine($"参数: {arg}");
}
// 可以定义方法
void SayHello(string name)
{
Console.WriteLine($"Hello, {name}!");
}
SayHello("World");
// 可以定义类
class Person
{
public string Name { get; set; }
}
var person = new Person { Name = "Alice" };
Console.WriteLine(person.Name);使用场景
适合顶级程序:
- 简单的控制台应用
- 脚本式程序
- 学习和实验代码
适合传统结构:
- 大型应用程序
- 多类项目
- 需要明确命名空间的项目
编译和运行过程
编译过程
C# 源代码 (.cs)
↓
C# 编译器 (csc.exe)
↓
中间语言 (IL) (.dll/.exe)
↓
公共语言运行时 (CLR)
↓
机器代码执行1. 编译命令
powershell
# 使用 dotnet CLI
dotnet build # 编译项目
dotnet build --configuration Release # 发布版本编译
# 直接使用编译器
csc Program.cs # 编译单个文件
csc /out:MyApp.exe Program.cs # 指定输出文件名2. 编译输出
bin/
├── Debug/
│ └── net8.0/
│ ├── HelloWorld.exe # 可执行文件
│ ├── HelloWorld.dll # 程序集
│ ├── HelloWorld.pdb # 调试信息
│ └── HelloWorld.runtimeconfig.json # 运行时配置
└── Release/
└── net8.0/
└── ...运行过程
1. 直接运行
powershell
# 运行编译后的程序
./bin/Debug/net8.0/HelloWorld.exe
# 使用 dotnet 运行
dotnet ./bin/Debug/net8.0/HelloWorld.dll2. 带参数运行
powershell
# 传递命令行参数
dotnet run -- arg1 arg2 arg3
# 或直接运行可执行文件
./HelloWorld.exe arg1 arg2 arg3csharp
// 在程序中处理参数
static void Main(string[] args)
{
Console.WriteLine($"参数数量: {args.Length}");
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($"参数 {i}: {args[i]}");
}
}基本输入输出
输出到控制台
csharp
// 基本输出
Console.WriteLine("Hello World!"); // 输出并换行
Console.Write("Hello "); // 输出不换行
Console.Write("World!\n"); // 手动换行
// 格式化输出
string name = "Alice";
int age = 25;
// 字符串插值(推荐)
Console.WriteLine($"姓名: {name}, 年龄: {age}");
// 复合格式化
Console.WriteLine("姓名: {0}, 年龄: {1}", name, age);
// 格式化数字
double price = 123.456;
Console.WriteLine($"价格: {price:C}"); // 货币格式
Console.WriteLine($"价格: {price:F2}"); // 保留2位小数
Console.WriteLine($"价格: {price:P}"); // 百分比格式从控制台输入
csharp
// 读取一行输入
Console.Write("请输入您的姓名: ");
string name = Console.ReadLine();
Console.WriteLine($"您好, {name}!");
// 读取单个字符
Console.Write("按任意键继续...");
ConsoleKeyInfo keyInfo = Console.ReadKey();
Console.WriteLine($"\n您按了: {keyInfo.Key}");
// 类型转换
Console.Write("请输入您的年龄: ");
string ageInput = Console.ReadLine();
int age = int.Parse(ageInput);
Console.WriteLine($"您的年龄是: {age}");
// 安全的类型转换
Console.Write("请输入一个数字: ");
string input = Console.ReadLine();
if (int.TryParse(input, out int number))
{
Console.WriteLine($"您输入的数字是: {number}");
}
else
{
Console.WriteLine("输入的不是有效数字");
}实践示例
示例 1:简单计算器
csharp
using System;
Console.WriteLine("=== 简单计算器 ===");
// 获取第一个数字
Console.Write("请输入第一个数字: ");
double num1 = double.Parse(Console.ReadLine());
// 获取运算符
Console.Write("请输入运算符 (+, -, *, /): ");
char op = Console.ReadLine()[0];
// 获取第二个数字
Console.Write("请输入第二个数字: ");
double num2 = double.Parse(Console.ReadLine());
// 计算结果
double result = op switch
{
'+' => num1 + num2,
'-' => num1 - num2,
'*' => num1 * num2,
'/' => num2 != 0 ? num1 / num2 : double.NaN,
_ => double.NaN
};
// 显示结果
if (double.IsNaN(result))
{
Console.WriteLine("无效的运算或除零错误!");
}
else
{
Console.WriteLine($"结果: {num1} {op} {num2} = {result}");
}示例 2:用户信息收集
csharp
using System;
Console.WriteLine("=== 用户信息收集 ===");
// 收集用户信息
Console.Write("姓名: ");
string name = Console.ReadLine();
Console.Write("年龄: ");
int age = int.Parse(Console.ReadLine());
Console.Write("邮箱: ");
string email = Console.ReadLine();
Console.Write("城市: ");
string city = Console.ReadLine();
// 显示收集的信息
Console.WriteLine("\n=== 用户信息确认 ===");
Console.WriteLine($"姓名: {name}");
Console.WriteLine($"年龄: {age}");
Console.WriteLine($"邮箱: {email}");
Console.WriteLine($"城市: {city}");
// 确认信息
Console.Write("\n信息是否正确? (y/n): ");
string confirm = Console.ReadLine().ToLower();
if (confirm == "y" || confirm == "yes")
{
Console.WriteLine("信息已保存!");
}
else
{
Console.WriteLine("请重新输入信息。");
}示例 3:命令行参数处理
csharp
using System;
// 检查命令行参数
if (args.Length == 0)
{
Console.WriteLine("用法: HelloWorld.exe <name> [age]");
Console.WriteLine("示例: HelloWorld.exe Alice 25");
return;
}
string name = args[0];
int age = 0;
// 检查是否提供了年龄参数
if (args.Length > 1)
{
if (int.TryParse(args[1], out age))
{
Console.WriteLine($"你好, {name}! 你 {age} 岁了。");
}
else
{
Console.WriteLine($"你好, {name}! 年龄参数无效。");
}
}
else
{
Console.WriteLine($"你好, {name}!");
}
// 显示所有参数
Console.WriteLine($"\n收到 {args.Length} 个参数:");
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($" 参数 {i}: {args[i]}");
}调试基础
设置断点
csharp
static void Main(string[] args)
{
Console.WriteLine("程序开始");
string name = "Alice"; // 在此行设置断点 (F9)
int age = 25;
Console.WriteLine($"姓名: {name}");
Console.WriteLine($"年龄: {age}");
Console.WriteLine("程序结束");
}调试技巧
- 使用断点:F9 设置/取消断点
- 单步执行:F10 逐过程,F11 逐语句
- 查看变量:鼠标悬停或使用监视窗口
- 即时窗口:在调试时执行表达式
调试输出
csharp
using System;
using System.Diagnostics;
static void Main(string[] args)
{
// 调试输出(只在调试模式下显示)
Debug.WriteLine("这是调试信息");
// 条件编译
#if DEBUG
Console.WriteLine("调试模式");
#else
Console.WriteLine("发布模式");
#endif
// 断言
Debug.Assert(args.Length >= 0, "参数数组不能为空");
}项目配置文件
.csproj 文件
xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>配置说明:
OutputType:输出类型(Exe=可执行文件)TargetFramework:目标框架版本ImplicitUsings:隐式 using 指令Nullable:可空引用类型检查
常用配置
xml
<PropertyGroup>
<!-- 应用程序信息 -->
<AssemblyTitle>我的应用程序</AssemblyTitle>
<AssemblyDescription>这是一个示例应用程序</AssemblyDescription>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<!-- 编译选项 -->
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<WarningsNotAsErrors>CS0618</WarningsNotAsErrors>
<!-- 输出配置 -->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>常见错误和解决方案
编译错误
1. CS5001: 程序不包含适合于入口点的静态 'Main' 方法
错误代码:
csharp
class Program
{
void Main(string[] args) // 缺少 static 关键字
{
Console.WriteLine("Hello");
}
}解决方案:
csharp
class Program
{
static void Main(string[] args) // 添加 static 关键字
{
Console.WriteLine("Hello");
}
}2. CS0103: 当前上下文中不存在名称 'Console'
错误代码:
csharp
// 缺少 using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello"); // Console 未定义
}
}解决方案:
csharp
using System; // 添加 using 指令
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello");
}
}运行时错误
1. 输入格式异常
csharp
// 不安全的转换
Console.Write("输入数字: ");
int number = int.Parse(Console.ReadLine()); // 可能抛出异常
// 安全的转换
Console.Write("输入数字: ");
string input = Console.ReadLine();
if (int.TryParse(input, out int number))
{
Console.WriteLine($"数字: {number}");
}
else
{
Console.WriteLine("输入格式错误");
}本章小结
本章介绍了 C# 程序的基础知识:
关键要点:
- 程序结构:using、namespace、class、Main 方法
- 编译运行:dotnet build 和 dotnet run
- 输入输出:Console.WriteLine 和 Console.ReadLine
- 调试技巧:断点、单步执行、变量监视
- 项目配置:.csproj 文件的基本配置
重要概念:
- Main 方法是程序入口点
- 顶级程序简化了代码结构
- 命令行参数通过 args 参数传递
- 调试是开发过程中的重要技能
下一步: 在下一章中,我们将学习 C# 的基础语法,包括变量、数据类型和运算符。