MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

C#基础语法与核心概念全面解析

2023-12-021.4k 阅读

C#基础语法

变量与数据类型

  1. 数据类型分类 C#的数据类型分为值类型和引用类型。值类型直接存储数据的值,而引用类型存储的是数据的引用地址。
  • 值类型 包括整数类型(如byteshortintlong)、浮点类型(floatdouble)、字符类型(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};
  1. 变量声明与初始化 变量在使用前必须先声明。声明变量时需要指定数据类型和变量名。可以在声明时初始化变量,也可以先声明后初始化。
// 声明并初始化
int num1 = 10;
// 先声明后初始化
int num2;
num2 = 20;

运算符

  1. 算术运算符 用于执行基本的数学运算,如加(+)、减(-)、乘(*)、除(/)、取模(%)。
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
  1. 赋值运算符 最基本的赋值运算符是=,用于将右边的值赋给左边的变量。还存在复合赋值运算符,如+=-=*=/=%=等。
int num = 5;
num += 3; // 等同于 num = num + 3; 此时num的值为8
  1. 比较运算符 用于比较两个值,结果为布尔值(truefalse)。常见的比较运算符有==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)。
int x = 10;
int y = 15;
bool result1 = x == y; // false
bool result2 = x < y; // true
  1. 逻辑运算符 用于组合或否定布尔表达式。主要的逻辑运算符有&&(逻辑与)、||(逻辑或)、!(逻辑非)。
bool condition1 = true;
bool condition2 = false;
bool andResult = condition1 && condition2; // false
bool orResult = condition1 || condition2; // true
bool notResult =!condition1; // false
  1. 位运算符 用于对整数类型的二进制位进行操作。例如&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)。
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

控制语句

  1. if - else语句 用于根据条件执行不同的代码块。
int score = 85;
if (score >= 90)
{
    Console.WriteLine("优秀");
}
else if (score >= 80)
{
    Console.WriteLine("良好");
}
else
{
    Console.WriteLine("需努力");
}
  1. 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;
}
  1. for循环 用于执行指定次数的循环。
for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}
  1. while循环 只要指定的条件为真,就会重复执行代码块。
int count = 0;
while (count < 3)
{
    Console.WriteLine(count);
    count++;
}
  1. do - while循环 先执行一次代码块,然后只要指定的条件为真,就会重复执行代码块。
int num = 0;
do
{
    Console.WriteLine(num);
    num++;
} while (num < 3);

数组

  1. 一维数组 数组是一种数据结构,用于存储相同类型的多个元素。一维数组的声明和初始化示例如下:
// 声明并初始化
int[] numbers = {1, 2, 3, 4, 5};
// 声明后再初始化
int[] anotherNumbers = new int[3];
anotherNumbers[0] = 10;
anotherNumbers[1] = 20;
anotherNumbers[2] = 30;
  1. 多维数组 多维数组可以是二维、三维等。以二维数组为例,它可以看作是一个表格结构。
// 二维数组声明并初始化
int[,] matrix = {
    {1, 2},
    {3, 4}
};
// 访问二维数组元素
int element = matrix[1, 0]; // 3
  1. 交错数组 交错数组是数组的数组,每个元素又是一个数组。
int[][] jaggedArray = new int[2][];
jaggedArray[0] = new int[3] {1, 2, 3};
jaggedArray[1] = new int[2] {4, 5};

C#核心概念

面向对象编程(OOP)基础

  1. 类与对象
  • 类是一种用户自定义的数据类型,它封装了数据(字段)和操作数据的方法。例如:
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();
  1. 封装 封装是将数据和操作数据的方法包装在一起,并对外部隐藏内部实现细节。在上面的Person类中,nameage字段被声明为private,只能在类内部访问。通过public方法Introduce来提供对这些数据的访问。
  2. 继承 继承允许一个类(子类)从另一个类(父类)继承成员。例如:
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();
  1. 多态 多态允许使用基类的引用访问派生类的对象,并根据对象的实际类型来调用适当的方法。实现多态的方式有虚方法和抽象类等。
  • 虚方法 在基类中使用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());

委托与事件

  1. 委托 委托是一种类型安全的函数指针,它允许将方法作为参数传递给其他方法。声明委托的语法如下:
public delegate void MyDelegate(int num);

可以定义一个符合委托签名的方法,并将该方法赋值给委托实例。

public void PrintNumber(int num)
{
    Console.WriteLine(num);
}

MyDelegate del = PrintNumber;
del(10);
  1. 事件 事件是基于委托的一种机制,用于实现发布 - 订阅模式。在一个类(发布者)中定义事件,其他类(订阅者)可以注册事件处理程序。例如:
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();

异常处理

  1. 异常的概念 异常是在程序执行过程中发生的错误或意外情况。C#通过异常处理机制来捕获和处理这些异常,以避免程序崩溃。
  2. try - catch - finally语句 try块中放置可能会抛出异常的代码,catch块用于捕获并处理异常,finally块中的代码无论是否发生异常都会执行。
try
{
    int result = 10 / 0; // 会抛出DivideByZeroException异常
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("除数不能为零: " + ex.Message);
}
finally
{
    Console.WriteLine("无论是否有异常,都会执行这里");
}
  1. 自定义异常 可以通过继承Exception类来创建自定义异常。
public class MyCustomException : Exception
{
    public MyCustomException(string message) : base(message)
    {
    }
}
try
{
    throw new MyCustomException("这是一个自定义异常");
}
catch (MyCustomException ex)
{
    Console.WriteLine(ex.Message);
}

泛型

  1. 泛型类 泛型允许在定义类、方法等时使用类型参数,从而提高代码的重用性和类型安全性。泛型类的定义示例如下:
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();
  1. 泛型方法 除了泛型类,还可以定义泛型方法。
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)

  1. LINQ的基本概念 LINQ是一种集成在C#语言中的查询技术,它允许以类似SQL的语法对各种数据源(如数组、集合、数据库等)进行查询。
  2. 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);
}
  1. 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);
}

异步编程

  1. 异步方法与async/await关键字 在C#中,可以使用asyncawait关键字来编写异步代码,避免阻塞主线程。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);
}
  1. Task和Task Task表示一个异步操作,Task<T>表示一个有返回值的异步操作。可以通过Task.Run方法来启动一个异步任务。
Task.Run(() =>
{
    // 异步执行的代码
    Console.WriteLine("异步任务正在执行");
});

Task<int> task = Task.Run(() =>
{
    // 有返回值的异步任务
    return 10 * 20;
});
int result = task.Result;

内存管理

  1. 垃圾回收(GC) C#采用自动垃圾回收机制来管理内存。垃圾回收器会定期检查不再被引用的对象,并回收它们占用的内存。开发人员不需要手动释放对象的内存。
  2. 堆和栈
  • 栈用于存储值类型变量和方法调用的上下文。栈的操作速度快,但大小有限。
  • 堆用于存储引用类型对象。垃圾回收主要针对堆上的对象。

反射

  1. 反射的概念 反射是指在运行时获取程序集、类型、方法等信息,并动态地创建对象、调用方法等。通过反射,可以在运行时检查和操作类型的元数据。
  2. 使用反射获取类型信息
Type type = typeof(Person);
PropertyInfo[] properties = type.GetProperties();
MethodInfo[] methods = type.GetMethods();
  1. 使用反射创建对象和调用方法
Type type = typeof(Person);
object instance = Activator.CreateInstance(type, "Tom", 25);
MethodInfo method = type.GetMethod("Introduce");
method.Invoke(instance, null);

特性(Attributes)

  1. 特性的概念 特性是一种向程序的元素(如类、方法、属性等)添加元数据的方式。C#提供了许多预定义的特性,也允许开发人员创建自定义特性。
  2. 预定义特性 例如[Serializable]特性用于标记一个类可以被序列化,[Obsolete]特性用于标记一个方法或类型已过时。
[Serializable]
public class MyClass
{
    // 类成员
}

[Obsolete("该方法已过时,请使用新方法")]
public void OldMethod()
{
    // 方法实现
}
  1. 自定义特性 可以通过继承System.Attribute类来创建自定义特性。
public class MyCustomAttribute : Attribute
{
    public string Message { get; set; }

    public MyCustomAttribute(string message)
    {
        Message = message;
    }
}
[MyCustom("这是一个自定义特性")]
public class TargetClass
{
    // 类成员
}

通过反射可以获取和使用特性的信息。

以上全面解析了C#的基础语法与核心概念,希望能帮助开发者更深入地理解和掌握C#语言,从而编写出高效、健壮的程序。