C#基础语法与核心概念全面解析
2023-12-021.4k 阅读
C#基础语法
变量与数据类型
- 数据类型分类 C#的数据类型分为值类型和引用类型。值类型直接存储数据的值,而引用类型存储的是数据的引用地址。
- 值类型
包括整数类型(如
byte
、short
、int
、long
)、浮点类型(float
、double
)、字符类型(char
)和布尔类型(bool
)等。例如:
int age = 25;
float height = 175.5f;
char gender = 'M';
bool isStudent = true;
- 引用类型
常见的引用类型有
string
、数组、类、接口等。例如:
string name = "John";
int[] numbers = {1, 2, 3, 4, 5};
- 变量声明与初始化 变量在使用前必须先声明。声明变量时需要指定数据类型和变量名。可以在声明时初始化变量,也可以先声明后初始化。
// 声明并初始化
int num1 = 10;
// 先声明后初始化
int num2;
num2 = 20;
运算符
- 算术运算符
用于执行基本的数学运算,如加(
+
)、减(-
)、乘(*
)、除(/
)、取模(%
)。
int a = 10;
int b = 3;
int sum = a + b; // 13
int difference = a - b; // 7
int product = a * b; // 30
int quotient = a / b; // 3
int remainder = a % b; // 1
- 赋值运算符
最基本的赋值运算符是
=
,用于将右边的值赋给左边的变量。还存在复合赋值运算符,如+=
、-=
、*=
、/=
、%=
等。
int num = 5;
num += 3; // 等同于 num = num + 3; 此时num的值为8
- 比较运算符
用于比较两个值,结果为布尔值(
true
或false
)。常见的比较运算符有==
(等于)、!=
(不等于)、>
(大于)、<
(小于)、>=
(大于等于)、<=
(小于等于)。
int x = 10;
int y = 15;
bool result1 = x == y; // false
bool result2 = x < y; // true
- 逻辑运算符
用于组合或否定布尔表达式。主要的逻辑运算符有
&&
(逻辑与)、||
(逻辑或)、!
(逻辑非)。
bool condition1 = true;
bool condition2 = false;
bool andResult = condition1 && condition2; // false
bool orResult = condition1 || condition2; // true
bool notResult =!condition1; // false
- 位运算符
用于对整数类型的二进制位进行操作。例如
&
(按位与)、|
(按位或)、^
(按位异或)、~
(按位取反)、<<
(左移)、>>
(右移)。
int num1 = 5; // 二进制为 00000101
int num2 = 3; // 二进制为 00000011
int andResult = num1 & num2; // 二进制 00000001,结果为1
int orResult = num1 | num2; // 二进制 00000111,结果为7
int xorResult = num1 ^ num2; // 二进制 00000110,结果为6
int notResult = ~num1; // 二进制 11111010,结果为 -6
int leftShiftResult = num1 << 2; // 二进制 00010100,结果为20
int rightShiftResult = num1 >> 2; // 二进制 00000001,结果为1
控制语句
- if - else语句 用于根据条件执行不同的代码块。
int score = 85;
if (score >= 90)
{
Console.WriteLine("优秀");
}
else if (score >= 80)
{
Console.WriteLine("良好");
}
else
{
Console.WriteLine("需努力");
}
- switch - case语句 用于根据一个表达式的值,从多个分支中选择一个执行。
int day = 3;
switch (day)
{
case 1:
Console.WriteLine("星期一");
break;
case 2:
Console.WriteLine("星期二");
break;
case 3:
Console.WriteLine("星期三");
break;
default:
Console.WriteLine("其他");
break;
}
- for循环 用于执行指定次数的循环。
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
- while循环 只要指定的条件为真,就会重复执行代码块。
int count = 0;
while (count < 3)
{
Console.WriteLine(count);
count++;
}
- do - while循环 先执行一次代码块,然后只要指定的条件为真,就会重复执行代码块。
int num = 0;
do
{
Console.WriteLine(num);
num++;
} while (num < 3);
数组
- 一维数组 数组是一种数据结构,用于存储相同类型的多个元素。一维数组的声明和初始化示例如下:
// 声明并初始化
int[] numbers = {1, 2, 3, 4, 5};
// 声明后再初始化
int[] anotherNumbers = new int[3];
anotherNumbers[0] = 10;
anotherNumbers[1] = 20;
anotherNumbers[2] = 30;
- 多维数组 多维数组可以是二维、三维等。以二维数组为例,它可以看作是一个表格结构。
// 二维数组声明并初始化
int[,] matrix = {
{1, 2},
{3, 4}
};
// 访问二维数组元素
int element = matrix[1, 0]; // 3
- 交错数组 交错数组是数组的数组,每个元素又是一个数组。
int[][] jaggedArray = new int[2][];
jaggedArray[0] = new int[3] {1, 2, 3};
jaggedArray[1] = new int[2] {4, 5};
C#核心概念
面向对象编程(OOP)基础
- 类与对象
- 类 类是一种用户自定义的数据类型,它封装了数据(字段)和操作数据的方法。例如:
public class Person
{
// 字段
private string name;
private int age;
// 构造函数
public Person(string n, int a)
{
name = n;
age = a;
}
// 方法
public void Introduce()
{
Console.WriteLine($"我叫{name},今年{age}岁。");
}
}
- 对象
对象是类的实例。通过
new
关键字创建对象。
Person person1 = new Person("Alice", 30);
person1.Introduce();
- 封装
封装是将数据和操作数据的方法包装在一起,并对外部隐藏内部实现细节。在上面的
Person
类中,name
和age
字段被声明为private
,只能在类内部访问。通过public
方法Introduce
来提供对这些数据的访问。 - 继承 继承允许一个类(子类)从另一个类(父类)继承成员。例如:
public class Student : Person
{
private string school;
public Student(string n, int a, string s) : base(n, a)
{
school = s;
}
public void Study()
{
Console.WriteLine($"{name}在{school}学习。");
}
}
这里Student
类继承自Person
类,它继承了Person
类的字段和方法,并添加了自己的school
字段和Study
方法。
Student student1 = new Student("Bob", 20, "ABC大学");
student1.Introduce();
student1.Study();
- 多态 多态允许使用基类的引用访问派生类的对象,并根据对象的实际类型来调用适当的方法。实现多态的方式有虚方法和抽象类等。
- 虚方法
在基类中使用
virtual
关键字定义虚方法,在派生类中使用override
关键字重写该方法。
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("动物发出声音");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("汪汪汪");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("喵喵喵");
}
}
通过基类引用调用方法时,会根据对象的实际类型调用相应的重写方法。
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.MakeSound(); // 汪汪汪
animal2.MakeSound(); // 喵喵喵
- 抽象类 抽象类是一种不能被实例化的类,它可以包含抽象方法(没有实现体的方法)。派生类必须重写抽象方法。
public abstract class Shape
{
public abstract double Area();
}
public class Circle : Shape
{
private double radius;
public Circle(double r)
{
radius = r;
}
public override double Area()
{
return Math.PI * radius * radius;
}
}
public class Rectangle : Shape
{
private double width;
private double height;
public Rectangle(double w, double h)
{
width = w;
height = h;
}
public override double Area()
{
return width * height;
}
}
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Console.WriteLine(circle.Area());
Console.WriteLine(rectangle.Area());
委托与事件
- 委托 委托是一种类型安全的函数指针,它允许将方法作为参数传递给其他方法。声明委托的语法如下:
public delegate void MyDelegate(int num);
可以定义一个符合委托签名的方法,并将该方法赋值给委托实例。
public void PrintNumber(int num)
{
Console.WriteLine(num);
}
MyDelegate del = PrintNumber;
del(10);
- 事件 事件是基于委托的一种机制,用于实现发布 - 订阅模式。在一个类(发布者)中定义事件,其他类(订阅者)可以注册事件处理程序。例如:
public class Publisher
{
public delegate void MyEventHandler();
public event MyEventHandler MyEvent;
public void RaiseEvent()
{
if (MyEvent!= null)
{
MyEvent();
}
}
}
public class Subscriber
{
public void HandleEvent()
{
Console.WriteLine("事件被处理");
}
}
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.MyEvent += subscriber.HandleEvent;
publisher.RaiseEvent();
异常处理
- 异常的概念 异常是在程序执行过程中发生的错误或意外情况。C#通过异常处理机制来捕获和处理这些异常,以避免程序崩溃。
- try - catch - finally语句
try
块中放置可能会抛出异常的代码,catch
块用于捕获并处理异常,finally
块中的代码无论是否发生异常都会执行。
try
{
int result = 10 / 0; // 会抛出DivideByZeroException异常
}
catch (DivideByZeroException ex)
{
Console.WriteLine("除数不能为零: " + ex.Message);
}
finally
{
Console.WriteLine("无论是否有异常,都会执行这里");
}
- 自定义异常
可以通过继承
Exception
类来创建自定义异常。
public class MyCustomException : Exception
{
public MyCustomException(string message) : base(message)
{
}
}
try
{
throw new MyCustomException("这是一个自定义异常");
}
catch (MyCustomException ex)
{
Console.WriteLine(ex.Message);
}
泛型
- 泛型类 泛型允许在定义类、方法等时使用类型参数,从而提高代码的重用性和类型安全性。泛型类的定义示例如下:
public class GenericBox<T>
{
private T value;
public void SetValue(T val)
{
value = val;
}
public T GetValue()
{
return value;
}
}
使用泛型类时,可以指定具体的类型参数。
GenericBox<int> intBox = new GenericBox<int>();
intBox.SetValue(10);
int result = intBox.GetValue();
GenericBox<string> stringBox = new GenericBox<string>();
stringBox.SetValue("Hello");
string str = stringBox.GetValue();
- 泛型方法 除了泛型类,还可以定义泛型方法。
public class GenericUtils
{
public static T GetMax<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0? a : b;
}
}
int maxInt = GenericUtils.GetMax(5, 10);
string maxStr = GenericUtils.GetMax("apple", "banana");
LINQ(Language - Integrated Query)
- LINQ的基本概念 LINQ是一种集成在C#语言中的查询技术,它允许以类似SQL的语法对各种数据源(如数组、集合、数据库等)进行查询。
- LINQ to Objects 对内存中的集合进行查询。例如:
int[] numbers = {1, 2, 3, 4, 5, 6};
var result = from num in numbers
where num % 2 == 0
select num;
foreach (int num in result)
{
Console.WriteLine(num);
}
- LINQ to XML 用于查询和操作XML数据。
XDocument doc = XDocument.Load("example.xml");
var elements = from element in doc.Descendants("Book")
where (string)element.Element("Author") == "John"
select element;
foreach (XElement element in elements)
{
Console.WriteLine(element.Element("Title").Value);
}
异步编程
- 异步方法与async/await关键字
在C#中,可以使用
async
和await
关键字来编写异步代码,避免阻塞主线程。async
关键字用于标记一个异步方法,await
关键字用于暂停异步方法的执行,直到其等待的任务完成。
public async Task<int> CalculateAsync()
{
await Task.Delay(2000); // 模拟一个耗时操作
return 10 + 20;
}
public async Task MainAsync()
{
int result = await CalculateAsync();
Console.WriteLine(result);
}
- Task和Task
Task
表示一个异步操作,Task<T>
表示一个有返回值的异步操作。可以通过Task.Run
方法来启动一个异步任务。
Task.Run(() =>
{
// 异步执行的代码
Console.WriteLine("异步任务正在执行");
});
Task<int> task = Task.Run(() =>
{
// 有返回值的异步任务
return 10 * 20;
});
int result = task.Result;
内存管理
- 垃圾回收(GC) C#采用自动垃圾回收机制来管理内存。垃圾回收器会定期检查不再被引用的对象,并回收它们占用的内存。开发人员不需要手动释放对象的内存。
- 堆和栈
- 栈 栈用于存储值类型变量和方法调用的上下文。栈的操作速度快,但大小有限。
- 堆 堆用于存储引用类型对象。垃圾回收主要针对堆上的对象。
反射
- 反射的概念 反射是指在运行时获取程序集、类型、方法等信息,并动态地创建对象、调用方法等。通过反射,可以在运行时检查和操作类型的元数据。
- 使用反射获取类型信息
Type type = typeof(Person);
PropertyInfo[] properties = type.GetProperties();
MethodInfo[] methods = type.GetMethods();
- 使用反射创建对象和调用方法
Type type = typeof(Person);
object instance = Activator.CreateInstance(type, "Tom", 25);
MethodInfo method = type.GetMethod("Introduce");
method.Invoke(instance, null);
特性(Attributes)
- 特性的概念 特性是一种向程序的元素(如类、方法、属性等)添加元数据的方式。C#提供了许多预定义的特性,也允许开发人员创建自定义特性。
- 预定义特性
例如
[Serializable]
特性用于标记一个类可以被序列化,[Obsolete]
特性用于标记一个方法或类型已过时。
[Serializable]
public class MyClass
{
// 类成员
}
[Obsolete("该方法已过时,请使用新方法")]
public void OldMethod()
{
// 方法实现
}
- 自定义特性
可以通过继承
System.Attribute
类来创建自定义特性。
public class MyCustomAttribute : Attribute
{
public string Message { get; set; }
public MyCustomAttribute(string message)
{
Message = message;
}
}
[MyCustom("这是一个自定义特性")]
public class TargetClass
{
// 类成员
}
通过反射可以获取和使用特性的信息。
以上全面解析了C#的基础语法与核心概念,希望能帮助开发者更深入地理解和掌握C#语言,从而编写出高效、健壮的程序。