C# 基础知识详解 从变量类型到面向对象编程 掌握核心概念与实战技巧

引言
C#(发音为 “C Sharp”)是由微软开发的一种现代、面向对象的强类型编程语言。作为 .NET 平台的核心语言,C# 结合了 C++ 的强大功能和 Visual Basic 的易用性,广泛应用于企业级应用开发、游戏开发(Unity)、移动应用和 Web 服务等领域。本文将从最基础的变量类型开始,逐步深入到面向对象编程的核心概念,并通过详细的代码示例帮助你掌握实战技巧。
无论你是编程新手还是有其他语言经验的开发者,这篇文章都将为你提供系统化的 C# 知识体系。我们将按照逻辑顺序展开:首先了解基本语法和数据类型,然后探讨控制流和函数,最后深入面向对象编程的精髓。
1. 变量类型与数据类型
1.1 基本数据类型
C# 是一种强类型语言,这意味着每个变量都有明确的数据类型。C# 的数据类型分为
值类型
和
引用类型
两大类。
值类型(Value Types)
值类型直接存储数据,分配在栈(Stack)上。常见的值类型包括:
整数类型
:
sbyte
:8 位有符号整数(-128 到 127)
byte
:8 位无符号整数(0 到 255)
short
:16 位有符号整数
ushort
:16 位无符号整数
int
:32 位有符号整数(最常用)
uint
:32 位无符号整数
long
:64 位有符号整数
ulong
:64 位无符号整数
浮点类型
:
float
:32 位单精度浮点数(精度约 7 位)
double
:64 位双精度浮点数(精度约 15-16 位,最常用)
decimal
:128 位十进制浮点数(用于财务计算,精度约 28-29 位)
其他值类型
:
bool
:布尔值(true 或 false)
char
:16 位 Unicode 字符
struct
:结构体(自定义值类型)
enum
:枚举类型
引用类型(Reference Types)
引用类型存储对内存中对象的引用(指针),分配在堆(Heap)上。常见的引用类型包括:
string
:字符串(不可变)
object
:所有类型的基类
class
:类
interface
:接口
delegate
:委托
array
:数组
1.2 变量声明与初始化
变量声明的基本语法是:
数据类型 变量名 = 初始值;
// 整数变量
int age = 25;
uint positiveNumber = 100;

// 浮点数变量
double price = 19.99;
decimal taxRate = 0.08m; // m 后缀表示 decimal

// 字符和字符串
char grade = ‘A’;
string name = “John Doe”;

// 布尔值
bool isStudent = true;

// 隐式类型推断(使用 var 关键字)
var city = “New York”; // 编译器自动推断为 string
var count = 10; // 编译器自动推断为 int
重要提示
:
使用
var
关键字时,变量必须在声明时初始化,因为编译器需要根据初始值推断类型。
decimal
类型需要使用
m
或
M
后缀,否则会被当作
double
处理。
1.3 类型转换
隐式转换(安全转换)
从小范围类型到大范围类型的自动转换:
int i = 100;
long l = i; // int 到 long(隐式转换)
double d = i; // int 到 double(隐式转换)

float f = 10.5f;
double d2 = f; // float 到 double(隐式转换)
显式转换(强制转换)
需要使用括号指定目标类型:
double d = 9.8;
int i = (int)d; // 结果为 9,小数部分被截断

long l = 1000L;
int i2 = (int)l; // 如果 long 值超出 int 范围,会发生溢出
使用 Convert 类
对于复杂类型转换,可以使用
Convert
类:
string numStr = “123”;
int num = Convert.ToInt32(numStr); // 字符串转整数

double d = 123.45;
string str = Convert.ToString(d); // 数字转字符串

// 注意:如果转换失败会抛出异常
try
{
int result = Convert.ToInt32(“abc”); // 会抛出 FormatException
}
catch (FormatException ex)
{
Console.WriteLine($”转换失败: {ex.Message}”);
}
安全转换(TryParse)
对于字符串到数字的转换,推荐使用
TryParse
方法避免异常:
string input = “123”;
int result;
if (int.TryParse(input, out result))
{
Console.WriteLine($”转换成功: {result}”);
}
else
{
Console.WriteLine(“转换失败”);
}

// C# 7.0+ 可以使用内联 out 变量
if (int.TryParse(input, out var num))
{
Console.WriteLine($”转换成功: {num}”);
}
1.4 常量
常量使用
const
关键字声明,必须在声明时初始化,之后不能修改:
const double PI = 3.14159;
const string COMPANY_NAME = “Microsoft”;

// const int x; // 错误:必须初始化
// PI = 3.14; // 错误:不能修改常量
2. 运算符与表达式
2.1 算术运算符
int a = 10, b = 3;

int sum = a + b; // 13(加法)
int diff = a – b; // 7(减法)
int product = a * b; // 30(乘法)
int quotient = a / b; // 3(整数除法,结果为 3)
int remainder = a % b; // 1(取模/取余)

double d1 = 10.0, d2 = 3.0;
double dQuotient = d1 / d2; // 3.333…(浮点除法)
注意
:整数除法会截断小数部分。如果需要浮点结果,至少一个操作数应为浮点类型。
2.2 赋值运算符
int x = 5;
x += 3; // 等价于 x = x + 3; 结果为 8
x -= 2; // 等价于 x = x – 2; 结果为 6
x *= 2; // 等价于 x = x * 2; 结果为 12
x /= 3; // 等价于 x = x / 3; 结果为 4
x %= 3; // 等价于 x = x % 3; 结果为 1
2.3 关系运算符
int a = 5, b = 10;

bool isEqual = (a == b); // false
bool notEqual = (a != b); // true
bool greater = (a > b); // false
bool less = (a < b); // true bool greaterOrEqual = (a >= b); // false
bool lessOrEqual = (a <= b); // true 2.4 逻辑运算符 bool isAdult = true; bool hasLicense = false; bool canDrive = isAdult && hasLicense; // false(逻辑与) bool canVote = isAdult || hasLicense; // true(逻辑或) bool isMinor = !isAdult; // false(逻辑非) // 短路求值:如果第一个条件为 false,则不计算第二个条件 if (isAdult && HasValidLicense()) // 如果 isAdult 为 false,HasValidLicense() 不会被调用 { // ... } 2.5 其他运算符 递增/递减 : int x = 5; int y = x++; // y = 5, x = 6(后置递增) int z = ++x; // z = 7, x = 7(前置递增) 空合并运算符 : string name = null; string displayName = name ?? "Guest"; // "Guest" 空条件运算符 : string text = null; int? length = text?.Length; // null(如果 text 为 null,结果为 null) 3. 控制流语句 3.1 条件语句 if-else 语句 int score = 85; if (score >= 90)
{
Console.WriteLine(“优秀”);
}
else if (score >= 80)
{
Console.WriteLine(“良好”);
}
else if (score >= 60)
{
Console.WriteLine(“及格”);
}
else
{
Console.WriteLine(“不及格”);
}
switch 语句
C# 的 switch 语句支持多种模式匹配(C# 7.0+):
// 传统 switch
int dayOfWeek = 3;
string dayName;

switch (dayOfWeek)
{
case 1:
dayName = “星期一”;
break;
case 2:
dayName = “星期二”;
break;
case 3:
dayName = “星期三”;
break;
default:
dayName = “未知”;
break;
}

// C# 7.0+ 模式匹配
object obj = “Hello”;
switch (obj)
{
case string s:
Console.WriteLine($”字符串: {s}”);
break;
case int i when i > 0:
Console.WriteLine($”正整数: {i}”);
break;
case null:
Console.WriteLine(“空值”);
break;
default:
Console.WriteLine(“其他类型”);
break;
}

// C# 8.0+ switch 表达式
var result = dayOfWeek switch
{
1 => “星期一”,
2 => “星期二”,
3 => “星期三”,
_ => “未知” // 默认情况
};
3.2 循环语句
for 循环
// 基本 for 循环
for (int i = 0; i < 5; i++) { Console.WriteLine($"迭代 {i}"); } // 嵌套循环 for (int i = 1; i <= 3; i++) { for (int j = 1; j <= i; j++) { Console.Write("*"); } Console.WriteLine(); } // 输出: // * // ** // *** while 循环 int count = 0; while (count < 5) { Console.WriteLine($"Count: {count}"); count++; } // do-while 循环(至少执行一次) int num = 10; do { Console.WriteLine($"Number: {num}"); num--; } while (num > 0);
foreach 循环
int[] numbers = { 1, 2, 3, 4, 5 };

foreach (int num in numbers)
{
Console.WriteLine(num);
}

// 遍历字符串
foreach (char c in “Hello”)
{
Console.Write(c + ” “);
}
// 输出:H e l l o
3.3 跳转语句
// break:跳出循环或 switch
for (int i = 0; i < 10; i++) { if (i == 5) { break; // 当 i=5 时跳出循环 } Console.WriteLine(i); } // continue:跳过当前迭代 for (int i = 0; i < 10; i++) { if (i % 2 == 0) { continue; // 跳过偶数 } Console.WriteLine(i); // 只输出奇数 } // return:从方法返回 int CalculateSum(int a, int b) { return a + b; } // goto:跳转到标签(谨慎使用) int x = 0; start: if (x < 3) { Console.WriteLine(x); x++; goto start; // 跳回到 start 标签 } 4. 方法(函数) 4.1 方法定义 方法是执行特定任务的代码块。基本语法: 访问修饰符 返回类型 方法名(参数列表) { 方法体 } public class Calculator { // 无参数无返回值 public void SayHello() { Console.WriteLine("Hello!"); } // 有参数无返回值 public void PrintMessage(string message) { Console.WriteLine(message); } // 有参数有返回值 public int Add(int a, int b) { return a + b; } // 多个返回值(C# 7.0+ 元组) public (int sum, int product) Calculate(int a, int b) { return (a + b, a * b); } } 4.2 参数传递方式 按值传递(默认) public void ModifyValue(int x) { x = x * 2; // 只修改局部副本 } int number = 5; ModifyValue(number); Console.WriteLine(number); // 输出 5(未改变) 按引用传递(ref) public void ModifyReference(ref int x) { x = x * 2; // 修改原始变量 } int number = 5; ModifyReference(ref number); Console.WriteLine(number); // 输出 10(已改变) 输出参数(out) public bool TryParseInt(string input, out int result) { if (int.TryParse(input, out result)) { return true; } return false; } // 调用 if (TryParseInt("123", out int value)) { Console.WriteLine($"解析成功: {value}"); } 可选参数和命名参数 public void CreateUser(string name, int age = 18, string role = "User") { Console.WriteLine($"Name: {name}, Age: {age}, Role: {role}"); } // 调用方式 CreateUser("Alice"); // 使用默认值 CreateUser("Bob", 25); // 指定 age,role 使用默认值 CreateUser("Charlie", role: "Admin"); // 命名参数,age 使用默认值 CreateUser("David", role: "Manager", age: 30); // 命名参数顺序任意 4.3 方法重载 方法名相同但参数列表不同: public class Printer { public void Print(string text) { Console.WriteLine($"文本: {text}"); } public void Print(int number) { Console.WriteLine($"整数: {number}"); } public void Print(string text, int times) { for (int i = 0; i < times; i++) { Console.WriteLine(text); } } } 4.4 扩展方法 扩展方法允许你向现有类型”添加”方法,而无需修改原始类: // 定义扩展方法(必须是静态类中的静态方法) public static class StringExtensions { public static bool IsNullOrEmpty(this string str) { return string.IsNullOrEmpty(str); } public static string Reverse(this string str) { char[] charArray = str.ToCharArray(); Array.Reverse(charArray); return new string(charArray); } } // 使用扩展方法 string text = "Hello"; if (!text.IsNullOrEmpty()) // 像实例方法一样调用 { Console.WriteLine(text.Reverse()); // 输出 "olleH" } 5. 数组与集合 5.1 数组 一维数组 // 声明和初始化 int[] numbers = new int[5]; // 创建大小为 5 的数组 numbers[0] = 1; numbers[1] = 2; // 声明时初始化 int[] scores = { 95, 87, 92, 78, 85 }; // 使用 var 和初始化器 var names = new string[] { "Alice", "Bob", "Charlie" }; // 访问数组元素 for (int i = 0; i < scores.Length; i++) { Console.WriteLine($"scores[{i}] = {scores[i]}"); } // foreach 遍历 foreach (int score in scores) { Console.WriteLine(score); } 多维数组 // 二维数组(矩阵) int[,] matrix = new int[3, 3] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; // 访问元素 int element = matrix[1, 2]; // 6 // 遍历二维数组 for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { Console.Write(matrix[row, col] + " "); } Console.WriteLine(); } 交错数组(数组的数组) int[][] jaggedArray = new int[3][]; jaggedArray[0] = new int[] { 1, 2 }; jaggedArray[1] = new int[] { 3, 4, 5 }; jaggedArray[2] = new int[] { 6 }; // 访问 int element = jaggedArray[1][2]; // 5 5.2 List (动态数组) using System.Collections.Generic; // 创建 List List numbers = new List();

// 添加元素
numbers.Add(10);
numbers.Add(20);
numbers.Add(30);

// 使用集合初始化器
List fruits = new List { “Apple”, “Banana”, “Orange” };

// 访问元素
Console.WriteLine(fruits[0]); // Apple

// 遍历
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}

// 常用操作
fruits.Insert(1, “Mango”); // 在索引 1 处插入
fruits.Remove(“Banana”); // 删除指定元素
fruits.RemoveAt(0); // 删除索引 0 处的元素
int count = fruits.Count; // 获取元素数量
bool hasApple = fruits.Contains(“Apple”); // 检查是否包含
5.3 Dictionary
(键值对)
using System.Collections.Generic;

// 创建 Dictionary
Dictionary ages = new Dictionary();

// 添加元素
ages[“Alice”] = 25;
ages[“Bob”] = 30;
ages.Add(“Charlie”, 35);

// 访问元素
int bobAge = ages[“Bob”]; // 30

// 安全访问(避免 KeyNotFoundException)
if (ages.TryGetValue(“David”, out int davidAge))
{
Console.WriteLine($”David’s age: {davidAge}”);
}
else
{
Console.WriteLine(“David not found”);
}

// 遍历键值对
foreach (KeyValuePair entry in ages)
{
Console.WriteLine($”{entry.Key}: {entry.Value}”);
}

// 检查键是否存在
if (ages.ContainsKey(“Alice”))
{
Console.WriteLine(“Alice exists”);
}

// 删除元素
ages.Remove(“Bob”);
5.4 其他常用集合
HashSet
:无序不重复集合
HashSet uniqueNumbers = new HashSet { 1, 2, 3, 2, 1 };
// 结果只包含 1, 2, 3
Queue
:先进先出队列
Queue queue = new Queue();
queue.Enqueue(“First”);
queue.Enqueue(“Second”);
string first = queue.Dequeue(); // “First”
Stack
:后进先出栈
Stack stack = new Stack();
stack.Push(1);
stack.Push(2);
int top = stack.Pop(); // 2
6. 面向对象编程(OOP)基础
6.1 类与对象
类的定义
public class Person
{
// 字段(私有,通常用小写开头)
private string name;
private int age;

// 属性(公有,大写开头)
public string Name
{
get { return name; }
set { name = value; } // value 是关键字,代表传入的值
}

public int Age
{
get { return age; }
set
{
if (value >= 0 && value <= 150) age = value; else throw new ArgumentException("年龄必须在 0-150 之间"); } } // 自动属性(C# 3.0+) public string Email { get; set; } = "default@example.com"; // 构造函数 public Person(string name, int age) { this.name = name; this.age = age; } // 无参构造函数 public Person() { name = "Unknown"; age = 0; } // 方法 public void SayHello() { Console.WriteLine($"Hello, I'm {name}, {age} years old"); } // 静态方法 public static int GetAdultAge() { return 18; } } 创建和使用对象 // 创建对象实例 Person person1 = new Person("Alice", 25); Person person2 = new Person(); // 使用无参构造函数 // 访问属性和方法 Console.WriteLine(person1.Name); // Alice person1.SayHello(); // 使用自动属性 person1.Email = "alice@example.com"; Console.WriteLine(person1.Email); // 使用静态方法 int adultAge = Person.GetAdultAge(); 6.2 访问修饰符 C# 有五个主要的访问修饰符: public :完全公开,任何代码都可访问 private :仅在声明它的类内部可访问 protected :类内部和派生类可访问 internal :同一程序集(assembly)内可访问 protected internal :同一程序集或派生类可访问 public class BaseClass { public int PublicField = 1; private int PrivateField = 2; // 只能在 BaseClass 内访问 protected int ProtectedField = 3; // BaseClass 和派生类可访问 internal int InternalField = 4; // 同一程序集内可访问 protected internal int ProtectedInternalField = 5; } public class DerivedClass : BaseClass { public void AccessFields() { Console.WriteLine(PublicField); // OK // Console.WriteLine(PrivateField); // 错误:无法访问 Console.WriteLine(ProtectedField); // OK Console.WriteLine(InternalField); // OK(同一程序集) Console.WriteLine(ProtectedInternalField); // OK } } 6.3 继承 继承允许一个类(派生类)继承另一个类(基类)的成员: // 基类 public class Animal { public string Name { get; set; } public Animal(string name) { Name = name; } public virtual void MakeSound() { Console.WriteLine($"{Name} makes a sound"); } public void Sleep() { Console.WriteLine($"{Name} is sleeping"); } } // 派生类 public class Dog : Animal { public string Breed { get; set; } public Dog(string name, string breed) : base(name) // 调用基类构造函数 { Breed = breed; } // 重写基类方法 public override void MakeSound() { Console.WriteLine($"{Name} barks: Woof! Woof!"); } // 派生类特有方法 public void Fetch() { Console.WriteLine($"{Name} is fetching"); } } // 使用 Animal animal = new Animal("Generic"); animal.MakeSound(); // Generic makes a sound Dog dog = new Dog("Buddy", "Golden Retriever"); dog.MakeSound(); // Buddy barks: Woof! Woof! dog.Sleep(); // Buddy is sleeping(继承自 Animal) dog.Fetch(); // Buddy is fetching(Dog 特有) 抽象类与抽象方法 public abstract class Shape { public string Color { get; set; } // 抽象方法(必须在派生类中实现) public abstract double CalculateArea(); // 非抽象方法(可以有实现) public void Display() { Console.WriteLine($"Shape with color {Color}"); } } public class Circle : Shape { public double Radius { get; set; } public override double CalculateArea() { return Math.PI * Radius * Radius; } } public class Rectangle : Shape { public double Width { get; set; } public double Height { get; set; } public override double CalculateArea() { return Width * Height; } } // 使用 Shape circle = new Circle { Color = "Red", Radius = 5 }; Shape rectangle = new Rectangle { Color = "Blue", Width = 4, Height = 6 }; Console.WriteLine($"Circle area: {circle.CalculateArea()}"); // 78.54 Console.WriteLine($"Rectangle area: {rectangle.CalculateArea()}"); // 24 6.4 多态 多态允许使用基类引用指向派生类对象,并在运行时调用正确的实现: // 使用上面的 Animal/Dog 示例 List animals = new List
{
new Animal(“Generic”),
new Dog(“Buddy”, “Labrador”),
new Dog(“Max”, “Poodle”)
};

foreach (Animal animal in animals)
{
animal.MakeSound(); // 运行时多态:每个对象调用自己的实现
}
// 输出:
// Generic makes a sound
// Buddy barks: Woof! Woof!
// Max barks: Woof! Woof!
6.5 接口
接口定义契约,规定实现类必须提供的成员:
// 定义接口
public interface IPlayable
{
void Play();
void Pause();
void Stop();
}

public interface IDownloadable
{
void Download();
}

// 实现接口
public class MusicPlayer : IPlayable, IDownloadable
{
public void Play()
{
Console.WriteLine(“Playing music”);
}

public void Pause()
{
Console.WriteLine(“Paused”);
}

public void Stop()
{
Console.WriteLine(“Stopped”);
}

public void Download()
{
Console.WriteLine(“Downloading music”);
}
}

// 使用接口
IPlayable player = new MusicPlayer();
player.Play();

// 接口组合
public class VideoPlayer : IPlayable
{
public void Play() { Console.WriteLine(“Playing video”); }
public void Pause() { Console.WriteLine(“Video paused”); }
public void Stop() { Console.WriteLine(“Video stopped”); }
}
接口默认方法(C# 8.0+)
public interface ILogger
{
void Log(string message);

// 默认实现
void LogError(string error)
{
Log($”ERROR: {error}”);
}
}

public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
// 不需要实现 LogError,使用默认实现
}

// 使用
ILogger logger = new ConsoleLogger();
logger.Log(“Info message”);
logger.LogError(“Something went wrong”); // 使用默认实现
6.6 封装、继承、多态总结
封装
:将数据和操作数据的方法绑定在一起,隐藏内部实现细节(通过类、属性、访问修饰符实现)
继承
:代码重用,建立类之间的层次关系
多态
:同一接口,不同实现,运行时根据对象类型调用正确方法
7. 高级概念与实战技巧
7.1 异常处理
try
{
// 可能抛出异常的代码
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[5]); // IndexOutOfRangeException
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine($”索引越界: {ex.Message}”);
}
catch (Exception ex)
{
Console.WriteLine($”发生未知错误: {ex.Message}”);
// 记录日志
// Logger.Log(ex);
}
finally
{
// 无论是否发生异常都会执行
Console.WriteLine(“清理资源…”);
}

// 自定义异常
public class InvalidAgeException : Exception
{
public InvalidAgeException(string message) : base(message) { }
}

public void SetAge(int age)
{
if (age < 0 || age > 150)
throw new InvalidAgeException($”无效年龄: {age}”);
}
7.2 命名空间(Namespaces)
// 定义命名空间
namespace MyCompany.MyProject
{
public class MyClass
{
// …
}
}

// 使用命名空间
using System;
using System.Collections.Generic;
using MyCompany.MyProject; // 引用自己的命名空间

namespace MyCompany.MyProject
{
public class Program
{
static void Main()
{
MyClass obj = new MyClass();
}
}
}
7.3 属性(Attributes)
// 使用预定义属性
public class Person
{
[Obsolete(“Use Name instead”, false)] // 标记为过时
public string NameField;

public string Name { get; set; }

[Required] // 标记为必需(用于数据验证)
public string Email { get; set; }
}

// 自定义属性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute : Attribute
{
public string Description { get; }

public MyCustomAttribute(string description)
{
Description = description;
}
}

[MyCustomAttribute(“This is a test class”)]
public class TestClass
{
// …
}
7.4 委托与事件
委托
委托是类型安全的函数指针:
// 定义委托
public delegate void NotificationDelegate(string message);

public class Notifier
{
public NotificationDelegate OnNotification;

public void SendNotification(string message)
{
OnNotification?.Invoke(message); // 空条件调用
}
}

// 使用委托
Notifier notifier = new Notifier();

// 方法1:直接赋值
notifier.OnNotification = (msg) => Console.WriteLine($”通知: {msg}”);

// 方法2:添加多个方法(多播委托)
notifier.OnNotification += DisplayMessage;
notifier.OnNotification += LogMessage;

notifier.SendNotification(“Hello World”);
// 输出:
// 通知: Hello World
// 显示: Hello World
// 记录: Hello World

void DisplayMessage(string msg) => Console.WriteLine($”显示: {msg}”);
void LogMessage(string msg) => Console.WriteLine($”记录: {msg}”);
事件
事件是封装的委托,提供更好的封装性:
public class Button
{
// 定义事件
public event EventHandler Click;

public void Press()
{
Console.WriteLine(“Button pressed”);
// 触发事件
Click?.Invoke(this, EventArgs.Empty);
}
}

public class Form
{
private Button button = new Button();

public Form()
{
// 订阅事件
button.Click += OnButtonClick;
}

private void OnButtonClick(object sender, EventArgs e)
{
Console.WriteLine(“Button click handled in Form”);
}

public void SimulateClick()
{
button.Press();
}
}

// 使用
Form form = new Form();
form.SimulateClick();
7.5 泛型
泛型允许编写可重用的代码,适用于多种数据类型:
// 泛型类
public class Box
{
public T Content { get; set; }

public void Display()
{
Console.WriteLine($”Box contains: {Content}”);
}
}

// 泛型方法
public T Max(T a, T b) where T : IComparable
{
return a.CompareTo(b) > 0 ? a : b;
}

// 泛型约束
public class Repository where T : class, new() // 必须是类且有无参构造函数
{
private List items = new List();

public void Add(T item)
{
items.Add(item);
}

public T GetById(int id)
{
// 假设 T 有 Id 属性(需要反射或接口)
return items.FirstOrDefault();
}
}

// 使用
Box intBox = new Box { Content = 123 };
Box strBox = new Box { Content = “Hello” };

int result = Max(10, 20); // 20
string maxStr = Max(“Apple”, “Banana”); // Banana
7.6 LINQ(语言集成查询)
LINQ 提供统一的查询语法:
using System.Linq;

List numbers = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// 方法语法
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
var sum = numbers.Sum();
var firstFive = numbers.Take(5);
var sorted = numbers.OrderByDescending(n => n);

// 查询语法(类似 SQL)
var query = from n in numbers
where n % 2 == 0
orderby n descending
select n;

// 复杂查询
List people = new List
{
new Person(“Alice”, 25),
new Person(“Bob”, 30),
new Person(“Charlie”, 20)
};

var adults = people.Where(p => p.Age >= 18)
.OrderBy(p => p.Name)
.Select(p => new { p.Name, p.Age });

foreach (var person in adults)
{
Console.WriteLine($”{person.Name}: {person.Age}”);
}

// 聚合操作
int count = numbers.Count();
double average = numbers.Average();
bool hasAny = numbers.Any(n => n > 10);
7.7 异步编程(async/await)
// 异步方法
public async Task DownloadDataAsync(string url)
{
using (HttpClient client = new HttpClient())
{
// await 暂停方法执行,但不阻塞线程
string result = await client.GetStringAsync(url);
return result;
}
}

// 调用异步方法
public async Task ProcessData()
{
Console.WriteLine(“开始下载…”);
string data = await DownloadDataAsync(“https://example.com”);
Console.WriteLine($”下载完成,数据长度: {data.Length}”);
}

// 多个异步操作
public async Task DownloadMultipleAsync()
{
var task1 = DownloadDataAsync(“https://example.com/page1”);
var task2 = DownloadDataAsync(“https://example.com/page2”);
var task3 = DownloadDataAsync(“https://example.com/page3”);

// 同时执行,等待所有完成
await Task.WhenAll(task1, task2, task3);

Console.WriteLine(“所有下载完成”);
}

// 异步流(C# 8.0+)
public async IAsyncEnumerable GenerateNumbersAsync()
{
for (int i = 1; i <= 5; i++) { await Task.Delay(100); // 模拟异步操作 yield return i; } } // 使用 await foreach (var num in GenerateNumbersAsync()) { Console.WriteLine(num); } 7.8 模式匹配(C# 7.0+) public class ShapeAreaCalculator { public double CalculateArea(object shape) { // is 模式 if (shape is Circle c) { return Math.PI * c.Radius * c.Radius; } // switch 表达式(C# 8.0+) return shape switch { Rectangle r => r.Width * r.Height,
Triangle t => (t.Base * t.Height) / 2,
null => 0,
_ => throw new ArgumentException(“未知形状”)
};
}
}

// 属性模式
public decimal CalculatePrice(Order order)
{
return order switch
{
{ Total: > 100 } => order.Total * 0.9m, // 9折
{ Total: > 50 } => order.Total * 0.95m, // 95折
_ => order.Total
};
}

// 元组模式
public string GetWeather(string season, string condition)
{
return (season, condition) switch
{
(“Winter”, “Snow”) => “滑雪的好天气”,
(“Summer”, “Sunny”) => “去海滩”,
(_, “Rain”) => “待在家里”,
_ => “未知天气”
};
}
7.9 记录(Records,C# 9.0+)
记录是用于数据模型的不可变引用类型:
// 定义记录
public record Person(string Name, int Age);

// 使用
var person1 = new Person(“Alice”, 25);
var person2 = new Person(“Alice”, 25);

Console.WriteLine(person1 == person2); // true(值相等性)

// with 表达式(创建副本并修改)
var olderPerson = person1 with { Age = 26 };

// 记录也可以有方法
public record Employee(string Name, int Age, string Department)
{
public string GetInfo() => $”{Name} ({Age}) – {Department}”;
}
7.10 模式匹配与解构
// 解构记录
var (name, age) = new Person(“Alice”, 25);
Console.WriteLine($”{name}, {age}”);

// 自定义解构
public class Point
{
public int X { get; }
public int Y { get; }

public Point(int x, int y) { X = x; Y = y; }

public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}

var (x, y) = new Point(10, 20);
8. 实战项目示例:简单的学生管理系统
让我们通过一个完整的项目来整合所学知识:
using System;
using System.Collections.Generic;
using System.Linq;

namespace StudentManagementSystem
{
// 自定义异常
public class StudentException : Exception
{
public StudentException(string message) : base(message) { }
}

// 学生类(记录,C# 9.0)
public record Student(string Id, string Name, int Age, double Grade);

// 学生管理器
public class StudentManager
{
private List students = new List();

// 添加学生
public void AddStudent(Student student)
{
if (students.Any(s => s.Id == student.Id))
throw new StudentException($”学生 ID {student.Id} 已存在”);

if (student.Age < 0 || student.Age > 150)
throw new StudentException(“年龄无效”);

students.Add(student);
Console.WriteLine($”添加学生: {student.Name}”);
}

// 查询学生
public Student GetStudent(string id)
{
return students.FirstOrDefault(s => s.Id == id);
}

// 获取优秀学生(成绩 >= 90)
public IEnumerable GetExcellentStudents()
{
return students.Where(s => s.Grade >= 90)
.OrderByDescending(s => s.Grade);
}

// 计算平均成绩
public double GetAverageGrade()
{
return students.Count > 0 ? students.Average(s => s.Grade) : 0;
}

// 删除学生
public bool RemoveStudent(string id)
{
var student = GetStudent(id);
if (student != null)
{
students.Remove(student);
Console.WriteLine($”删除学生: {student.Name}”);
return true;
}
return false;
}

// 显示所有学生
public void DisplayAllStudents()
{
if (!students.Any())
{
Console.WriteLine(“没有学生记录”);
return;
}

Console.WriteLine(“\n=== 所有学生 ===”);
foreach (var student in students)
{
Console.WriteLine($”ID: {student.Id}, Name: {student.Name}, Age: {student.Age}, Grade: {student.Grade}”);
}
}
}

// 主程序
class Program
{
static async Task Main(string[] args)
{
var manager = new StudentManager();

try
{
// 添加学生
manager.AddStudent(new Student(“S001”, “Alice”, 20, 95.5));
manager.AddStudent(new Student(“S002”, “Bob”, 21, 88.0));
manager.AddStudent(new Student(“S003”, “Charlie”, 19, 92.5));
manager.AddStudent(new Student(“S004”, “David”, 22, 78.0));

// 显示所有学生
manager.DisplayAllStudents();

// 查询优秀学生
Console.WriteLine(“\n=== 优秀学生 ===”);
var excellentStudents = manager.GetExcellentStudents();
foreach (var student in excellentStudents)
{
Console.WriteLine($”{student.Name}: {student.Grade}”);
}

// 计算平均成绩
Console.WriteLine($”\n平均成绩: {manager.GetAverageGrade():F2}”);

// 模拟异常
// manager.AddStudent(new Student(“S001”, “Duplicate”, 20, 90)); // 会抛出异常

// 异步操作示例
await SimulateAsyncOperation();
}
catch (StudentException ex)
{
Console.WriteLine($”错误: {ex.Message}”);
}
catch (Exception ex)
{
Console.WriteLine($”未知错误: {ex.Message}”);
}
}

static async Task SimulateAsyncOperation()
{
Console.WriteLine(“\n开始异步操作…”);
await Task.Delay(1000); // 模拟耗时操作
Console.WriteLine(“异步操作完成”);
}
}
}
9. 最佳实践与性能优化
9.1 命名规范
类名、方法名、属性名
:PascalCase(如
StudentManager
)
私有字段
:camelCase,前缀下划线(如
_studentCount
)
常量
:全大写(如
MAX_AGE
)
接口
:前缀
I
(如
IRepository
)
布尔属性
:使用
Is
、
Has
、
Can
前缀(如
IsActive
)
9.2 字符串操作优化
// 不好的做法(频繁创建新对象)
string result = “”;
for (int i = 0; i < 1000; i++) { result += i.ToString(); // 每次都创建新字符串 } // 好的做法(使用 StringBuilder) var sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.Append(i); } string result = sb.ToString(); 9.3 集合操作优化 // 预先指定容量(如果知道大小) var list = new List(1000); // 避免多次扩容

// 使用 HashSet 进行快速查找
var hashSet = new HashSet(list);

// 使用字典进行 O(1) 查找
var dict = list.ToDictionary(x => x);
9.4 使用 using 语句
// 自动释放资源
using (var reader = new StreamReader(“file.txt”))
{
string content = reader.ReadToEnd();
// reader.Dispose() 会自动调用
}

// C# 8.0+ using 声明
using var reader = new StreamReader(“file.txt”);
string content = reader.ReadToEnd();
// 在作用域结束时自动释放
9.5 空值处理最佳实践
// 使用空合并运算符
string name = null;
string displayName = name ?? “Guest”;

// 使用空条件运算符
int? length = name?.Length;

// 使用空值传播(C# 6.0+)
string street = person?.Address?.Street;

// 使用空值断言(谨慎使用)
string requiredName = name!; // 告诉编译器”我知道它不为空”
9.6 避免装箱和拆箱
// 装箱:值类型 -> 引用类型(性能损失)
object obj = 123; // int 装箱为 object

// 拆箱:引用类型 -> 值类型(可能出错)
int value = (int)obj; // 拆箱

// 使用泛型避免装箱
List list = new List(); // 不会装箱
10. 总结
本文详细介绍了 C# 的核心概念,从基础的变量类型到高级的面向对象编程技巧。我们涵盖了:
基础语法
:变量、数据类型、运算符和控制流
方法与函数
:定义、参数传递、重载和扩展方法
数据结构
:数组、List、Dictionary 等集合
面向对象编程
:类、对象、继承、多态、接口
高级特性
:异常处理、泛型、LINQ、异步编程、模式匹配
实战项目
:学生管理系统整合所有概念
最佳实践
:性能优化和代码规范
C# 是一门不断发展的语言,建议持续关注新版本特性(如 C# 10、11、12 的新功能)。通过实践项目来巩固知识,逐步构建复杂的应用程序。
下一步学习建议
:
深入学习 .NET 平台(ASP.NET Core、Entity Framework)
学习设计模式和架构原则
探索单元测试(xUnit、NUnit)
了解依赖注入和 IoC 容器
学习 WPF 或 Blazor 等 UI 框架
希望这篇文章能帮助你掌握 C# 的核心概念与实战技巧!