Skip to content

C#

基本特点

  • 面向对象

语法特性

变量

  • 值类型(数字):
    • 整数: byte, sbyte, short, ushort, long, ulong, int, uint, char
    • 十进制: decimal
    • 浮点: float, double
    • 其它: bool
    • string(只能用双引号)
    • object
    • dynamic
    • null
    • point

类型转换

隐式

cs
    byte tmp = 1;
    int res = tmp;

显式(pure)

cs
    byte tmp = 1;
    int res = (int)tmp;

显式(Convert, Parse, TryParse)

cs
    int tmp = 32;
    string res = Convert.ToString(tmp);

    string res2 = tmp.ToString();
    double res3 = double.parse(tmp);
    bool isSuccess = double.TryParse(tmp);

IO

基础IO

cs
    string userInput = Console.ReadLine();

    Console.WriteLine(userInput);

常量

定义与使用方法

cs
    const int num = 32;

字符串常量

cs
    string text = "xxx";
    string textTrans = @"xxx\txxx";

运算符

运算符逻辑与JavaScript类似, 不同的是c#全等运算就是==

基础运算符

cs
    算术运算: + - ++ -- % / *
    关系运算: == != >= <= > <
    逻辑运算: || && !
    赋值运算: = += -= *= /= %= <<= >>= &= ^= |=

特殊运算符

cs
    sizeof()
    typeof()
    ?:
    & *
    is
    as ( 强制类型转换, 失败不会抛异常

流程控制

与大部分语言类似: if类, switch类, 三元表达式

循环

与大部分语言类似, 有for和while类循环, 以及foreach:

  • while & do whilecacc
  • for
  • foreach

语言特性

方法

方法的语法组成

cs
    <access specifler> <return type> <method name> (parameter list) {
        method body
    }

传参

传参分为三种:

  • 输出

值传递与其它语言类似, 址传递需要使用ref进行声明

cs
    public void xMethod(ref numRef){
        numRef += 1;
    }
    int num = 32;
    xMethod(ref num);

使用输出参数可以从函数中返回两个值, 其会把方法的输出数据赋值给自己, 其它方面类似引用参数

cs
    public void outputValue(out num){
       num = 100;
    }
    int tmp = 32;
    outputValue(out tmp)

可空类型

单问号(?), 意思是Nullable类型

cs
    int? tmp = 3;
    等同于
    Nullable<int> tmp = new Nullable<int>(3);

声明默认值

cs
    int tmp; // 默认值为0
    int? tmp; 默认值为null
    int? tmp = new Int?();

声明一个null变量

cs
    <data type>? <var name> = null;

合并运算符 (??) 若前者值为null, 啧返回第二个, 效果类似于 || 或判断是否为空的三元表达式

cs
    int? num = null;
    int num2 = num ?? 100;
    // or
    int num3 = (num == null) ? 100 : num

数组

数组是一种用于存储固定大小、同一类型元素的集合, 其在c#中为引用类型, 需要通过new来赋值

  • 类型安全
  • 固定长度
  • 索引访问
  • 多维

数组被创建时, c#会根据不同的数据类型赋予默认值, 如int[]元素默认值为0 数组作为参数传递时, 传递地址

cs
   <data type>[] <data name> = new <data type>[length];

   // 赋值字面量
   int[] tmp = {1, 2, 3, 4}

二维数组 语法上略有不同, 需要在创建时指定行列数量

cs
    // ,将空间一分为二, 代表data type为二维数组
    string [,] names;
    int [,] nums = new Int[2, 3]{
        {0, 1, 2},
        {3, 4, 5}
    }
    // 访问
    int aimNum = nums[0, 2]

交错数组 交错数组是一维数组

cs
    int[][] nums = new int[2][]{new int[]{1,2,3}, new int[]{4,5,6}};

Array类 Array为数组基类, namespace为System: System.Array

Properties

  • Length
  • Rank 获取维度
  • IsFixedSize
  • IsReadOnly
  • IsSynchronized 是否线程安全
  • SyncRoot 同步多线程下数组访问对象

Methods

  • Clear 范围内设置为0 false null的其中一个
  • Copy(Arr, Arr, Len) A复制到长度为Len的B
  • CopyTo(Arr, Len)
  • GetLength / GetLongLength
  • GetLowerBound / GetUpperBound 维度下 / 上界
  • GetType
  • GetValue(index) / SetValue(Obj, index) 获取 / 设置index位置的值
  • IndexOf(Arr, Obj)
  • Sort(Arr) / Reverse(Arr)
  • ToString()
  • Clone() 浅拷贝@
  • Exist(Arr, x=>x==xxx) -> bool
  • AsReadOnly()
  • Fill()
  • ForEach()
  • TrueForAll(Arr, x=>x==xxx)
  • Resize(Arr, newSize)
  • BinarySearch(Arr, value)
  • Find类

字符串

基础使用

cs
    string tmp = "";
    string[] tmp = {"1", "2", "3"}

Format使用

cs
    DateTime waiting = new DateTime(2024, 10, 24, 00, 00, 00)
    string time = String.Format("{0:t} on {0:D}")

Properties

  • Chars
  • Length

Methods

  • Compare
  • Concat
  • Contains
  • Copy
  • CopyTo
  • StartsWith / EndsWith
  • Equals
  • indexOf
  • Insert
  • IsNullOrEmpty
  • Join
  • Remove
  • Replcae
  • Split
  • Trim
  • ToLower / ToUpper
  • ToCharArray
  • SubString

结构体

结构体在c#中是轻量级的数据类型, 适用于定义较为简单的数据

  • 可实现多个接口
  • 可以省略new, 初始化之后才会被赋值
  • 分配于栈
  • 值类型

结构体与类的区别

  • 结构体是Value Type; 类是Reference Type
  • 继承与多态: 结构体不支持, 类支持
  • 构造函数: 结构体不能有无参的构造函数, 类可以
  • 存储与传递:
    • 结构体是值, 类是址;
    • 结构体存储于栈, 类存储于堆;
    • 结构体更加轻量化, 类涉及更多的内存开销与管理
    • 结构体不可为null, 需要设置为Nullable<T>或T?; 类可以为null

枚举

用法

cs
    enum MODE {dev, prod, test}

特性

  • 类的默认访问符为inernal; 成员的默认访问符为private
  • 成员即为对象的属性, 默认情况下保持私有以实现封装

语法

cs
    <access specifiler> class {}

构造函数

  • 与类名完全相同
  • 无返回类型

构析函数 特点:

  • 无返回
  • 无参数
  • 不可被继承与重载

作用: 结束程序前释放资源 使用: 构造函数前添加~

cs
    ~<Construct Function Name>(){}

静态成员 可以使用static将成员定义为静态, 即便有多个类的实例被创建, 其静态成员唯一

封装 访问修饰符, 权限逐步缩小

  • public
  • internal / protected internal
  • protected
  • private

继承与多态 C#支持单继承与接口的 多继承 基类也称作父类, 派生类也称作子类

为什么可继承的语言语法中, 子类的构造函数旺旺需要调用父类的构造函数?

子类对象依赖父类, 所以子类对象需要在父类对象创建后才能被创建

类继承的使用

cs
    public class Shape {}
    public class Rectangle: Shape{
        public Shape():base(){}
    }

接口继承的使用

cs
    interface BaseInterface {
        void MethodA();
    }
    interface NormalInterface: BaseInterface{
        void MethodB();
    }
    // 类对接口的implement, 与继承的写法相同
    class ImplementClass: NormalInterface{
        public void MethodA(){...}
        public void MethodB(){...}
    }

接口的多继承 使用

cs
    interface InterfaceA {...}
    interface InterfaceB {...}
    class ImplementClass: InterfaceA, InterfaceB{...}

多态的类别

  • 静态多态性(overload): 编译时
  • 动态多态性(abstrct & virtual): 运行时

静态: return type必须相同, 才可以说是单个方法的重载

cs
    public class TestStatic{
        public void test(){}
        public void test(int num){}
    }

动态 (!!!没搞懂)

运算符重载 (略)

接口

通常接口名以I开头 使用

cs
    interface IName{
        <access specifiler> <return type> <name>(); // for method
        <access specifiler> <data type> <name>; // for regular data
    }

命名空间

诞生原因: 区分同名标识符 特点:

  • 可嵌套(使用.访问内嵌namespace)
  • 当A.xxx.method()与B.xxx.method被同一个文件导入后, 则系统会无法确认具体使用哪个方法
cs
    using System;
    namespace N1{...}
    namespace N2{...}
    class Test{
        // 互不干扰
        N1.method();
        N2.method();
    }

using(包导入) 基本使用

cs
    using System;
    using N1;
    using N2;
    class Test{
        public void run(){
           // 全称为System.Console.WriteLine(); 使用using XXX相当于把XXX包含的所有标识符都导入至当前文件 Console.WriteLine("RUN");
        }
    }

导入静态方法(using static)

cs
    using static System.Math;

Alias

cs
    using alias = OutterNamespace.InnerNamespace;

实例绑定

cs
    using (
        int predefinedData = 32;
    )

预处理指令

条件编译 #define #undef #if #elif #else #endif

日志 #warning #error

可读性 #region #endregion

其它 #line #pragma #nullable

正则表达式

(略)

异常处理

try catch finally

cs
    try{}
    catch(Exception e){}
    finally{}

异常类 IO: System.IO.IOException out of range: System.IndexOutOfRangeException null object: System.NullReferenceException zero: System.DivideByZeroException cast: System.InvalidCastException memory: System.OutOfMemoryException stack: System.StackOverflowExceptio

文件读写

binary data: BinaryReader / BinaryWriter

path: Path

buffer: BufferedStream StreamReader / StreamWriter

str: StringReader / StringWriter

dir: Directory / DirectoryInfo

file: File / FileInfo / FileStream

memory: MemoryStream

其它 DriveInfo

文件读写 文件流 / 基础文件读写 (FileStream) 参数

  • FileMode:
    • Append
    • Create / CreateNew
    • Open / OpenOrCreate
    • Truncate
  • FileAccess:
    • Read / Write / ReadWrite
  • FileShare
    • Inheritable
    • None
    • Read / Write / ReadWrite
    • Delete
cs
    FileStream file = new FileStream('test.csv', FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)

文本文件读写 (StreamReader / StreamWriter) (略)

二进制文件读写 (BinaryReader, BinaryWriter)

Windows FS

cs
string dirPath = @"D:\TestDir";
string filePath = @"D:\TestDir\TestFile.txt";
Console.WriteLine("<<<<<<<<<<<{0}>>>>>>>>>>", "文件路径");
//获得当前路径
Console.WriteLine(Environment.CurrentDirectory);
//文件或文件夹所在目录
Console.WriteLine(Path.GetDirectoryName(filePath));     //D:\TestDir
Console.WriteLine(Path.GetDirectoryName(dirPath));      //D:\
//文件扩展名
Console.WriteLine(Path.GetExtension(filePath));         //.txt
//文件名
Console.WriteLine(Path.GetFileName(filePath));          //TestFile.txt
Console.WriteLine(Path.GetFileName(dirPath));           //TestDir
Console.WriteLine(Path.GetFileNameWithoutExtension(filePath)); //TestFile
//绝对路径
Console.WriteLine(Path.GetFullPath(filePath));          //D:\TestDir\TestFile.txt
Console.WriteLine(Path.GetFullPath(dirPath));           //D:\TestDir
//更改扩展名
Console.WriteLine(Path.ChangeExtension(filePath, ".jpg"));//D:\TestDir\TestFile.jpg
//根目录
Console.WriteLine(Path.GetPathRoot(dirPath));           //D:\
//生成路径
Console.WriteLine(Path.Combine(new string[] { @"D:\", "BaseDir", "SubDir", "TestFile.txt" })); //D:\BaseDir\SubDir\TestFile.txt
//生成随即文件夹名或文件名
Console.WriteLine(Path.GetRandomFileName());
//创建磁盘上唯一命名的零字节的临时文件并返回该文件的完整路径
Console.WriteLine(Path.GetTempFileName());
//返回当前系统的临时文件夹的路径
Console.WriteLine(Path.GetTempPath());
//文件名中无效字符
Console.WriteLine(Path.GetInvalidFileNameChars());
//路径中无效字符
Console.WriteLine(Path.GetInvalidPathChars());

进阶属性

Attribute: 特性 / 元信息 Reflection: 反射 Property: 属性(定义类成员而非方法的访问和设置, 即访问器, 用于隐藏字段较多)

cs
    public void Demo(){
        get {
            return xxx;
        }
        set {
            xxx = ooo;
        }
    }
    // 自动实现
    public string GetName {get; set;}

    // 只读; 只写同理
    public string GetName {get;}

    // 计算属性 computed
    public string GetDynamic {
        get {
            return xxx + ooo;
        }
    }
    // abstract
    public abstract string Name {get; set;}

索引器: 与大部分语言相同, c#可以自定义索引器

委托

委托是类, 是用来包裹对应函数的外衣 需要满足的条件

  • return type 为空
  • params 为空

原始用法

cs
    // 声明
    delegate <return type> <delegate-name> <parameter list>

进阶用法

cs
    // 无返回值使用action
    Action<T> action = new Action<T>();
    action()

    // 有返回值使用function
    var Func<T> func = new Function<T>();
    var res = func();

    var Func func = ()=>{
        return xxx;
    }
    func()

事件

集合 Collection

用于存储和检索的类

  • Stack: Stack
  • Queue: Queue
  • List: ArrayList; SortedList
  • Hash Table: HashTable
  • Array: BitArray

泛型 Generic

与TS类似;c#有泛型委托与泛型约束 使用

cs
    // 用于类
    class Test <T>{}
    // 用于成员
    public T Test(){}
    // 用于参数
    ...(T paramDemo){}

匿名函数

Lambda表达式 与js类似

cs
    delegate void NumberChanger(int n);

    NumberChanger nc = x => Console.WriteLine($"Lambda Expression: {x}");

匿名方法

cs
    // 声明
    delegate void Method();
    // 实现
    Method method = Method(){
        ...
    }; // 末尾要加;

不安全代码

通过unsafe修饰符标记的代码会允许使用指针变量, 这种代码称为不安全代码;

cs
    public static unsafe void Main(string[] args){
        int num = 32;
        int* p = &num;
    }

对不安全代码进行编译时, 需要追加/unsafe参数;VS中可能需要先启用不安全代码才能使用

cs
    csc /unsafe xxx.cs

c#中的变量受GC影响, 可能会在运行时更改内存地址, 此时需要指定变量内存地址固定, 这时的指针变量才有意义;或者采取另一种方法: 将变量分配到堆栈内存上

cs
    fixed()

多线程

类: System.Threading.Thread 状态:

  1. 未启动(创建实例后, Start之前)
  2. 就绪
  3. 不可运行(调用了Sleep或Wait, IO阻塞)
  4. 结束(dead)

主线程 c#启动时, 主线程会被自动创建出来, 所以获取主线程就是在获取当前线程

cs
    using System.Threading;
    ...
    Thread th = Thread.CurrentThread;
    th.Name = "MainThread";

Thread类 属性

  • Name
  • Priority
  • ThreadState
  • ManagedThreadId
  • IsAlive / IsBackground / IsThreadPoolThread
  • CurrentContext
  • CurrentCulture
  • CurrentPrincipal
  • CurrentThread
  • CurrentUICulture
  • ExecutionContext

方法

  • Abort 终止线程
  • ResetAbort 取消Abort请求
  • Start 开始线程
  • Sleep 暂停线程
  • Interrupt 终端在WaitSleepJoin状态的线程
  • Join 阻塞线程
  • BeginCriticalRegion / EndCriticalRegion
  • ...

Last updated: