Vico Bill< 刘 利 波 > 的个人网站

记录关于学习、工作中的技术点滴

C,C++,Rust,Ruby爱好者;热衷于游戏开发、任务自动化与跨平台;沉迷于游戏引擎与图形表现;深信'简单、多元'哲学的力量。


访问主页

编程语言-C#

C#基础

基本数据类型:byte,sbyte,short,ushort,int,uint,long,ulong,float,double,dcimal(128位十进制),bool,char,string;IntPtr,UIntPtr,object(所有类型的基类); delegate(匿名函数类型);

复合数据类型:数组[], enum, struct ,class,interface

流程控制语句:if..else, switch..case;while.., do..while,for,foreach

跳转语句:break,continue,goto,throw,return,yield

C# 高级概念

  • 泛型:用于强类型的通用编程,避免类型转换(通常转换为object后操作)带来的性能损失。如ArrayList 可以添加不同类型的数据,但这些数据都是转换成object之后进行存储,这通常用于异型集合。List则是同型集合,更利于编译器的类型检查。

特殊关键字

delegate

delegate:用于封装命名方法或匿名方法的引用类型-。

delegate T MathOp<T>(T a, T b);

public static int sum(int a,int b) { return a + b;}
public static int del(int a,int b) {return a - b;}

MathOp<T> op = new MathOp<int>(sum);

MathOp<T> multiOp = new MathOp<int>();
multiOp = sum + del;
op = multiOp - del;

public delegate void EventHandler(object sender,EventArgs e);
public event EventHandler RaiseEvent;

public delegate void EventHandler<T>(object sender,T e);
public event EventHandler<MyEventArgs> RaiseEvent;

在以下情况下,请使用委托:

  • 当使用事件设计模式时。
  • 当封装静态方法可取时。
  • 当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
  • 需要方便的组合。
  • 当类可能需要该方法的多个实现时。

在以下情况下,请使用接口:

  • 当存在一组可能被调用的相关方法时。
  • 当类只需要方法的单个实现时。
  • 当使用接口的类想要将该接口强制转换为其他接口或类类型时。
  • 当正在实现的方法链接到类的类型或标识时:例如比较方法。

修饰符列表

修饰符 作用
async 可修饰方法、lambada表达式等。表明为异步方法。
const 修饰变量为不可变。
extern 外部实现的方法。如其他dll等。
static 声明属于类型本身而不是特定对象的成员。
unsafe 表明涉及到指针的操作。
virtual 声明方法、属性、索引器、事件等,表示它们可在派生类中被重写。
volatile 指示一个字段可由多个同时执行的线程修改。
event 声明事件
override 扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现需要override修饰符。
readonly 1. 声明字段只读 2. 修饰struct是不可变的 3. 修饰方法返回的值是只读的。
sealed 修饰类是不可被继承的。

访问修饰符:

关键字 作用
public 访问不受限
protected 限于当前类或派生类
private 限于当前类

语句关键字:

关键字 作用
if..else,switch..case 分支选择
do..while,while,for,foreach..in 迭代
break,continue,return 跳转
try..catch..finally, throw 异常
checked,unchecked 检测结果溢出异常或不检测
fixed 用在unsafe的上下文中,也可分配固定大小缓冲区
lock 线程互斥

参数关键字:

关键字 作用
params 数目可变的参数
in,out 引用传递参数。in不可被修改,out必须被修改。
ref 指示按引用传递的值

命名空间关键字:

关键字 作用
namespace 声明命名空间
using 1. 创建别名或导入命名空间 2. 定义域,自动释放

运算符关键字:

关键字 作用
as 引用类型转换
await 应用于异步方法中的任务,在方法执行中插入挂起点,直至任务完成。
is 检测类型是否相同
new 1. 创建对象和调用构造函数 2. 隐藏基类成员的继承成员 3. 限制可能用作泛型声明中类型形参的实际参数。
sizeof 获取类型(简单数据类型,枚举,指针,结构体)大小
typeof 获取运行时类型

转换关键字:

关键字 作用
explicit 必须显式转换
implicit 隐式转换
operator 重载内置运算符,或在类或结构生命中提供用户定义的转换。

访问关键字:

关键字 作用
base 访问基类成员
this 引用类的当前实例。

上下文关键字:

关键字 作用
add,remove 自定义事件访问器
get,set 访问器方法
global 全局命名空间
partial 1. 将类、接口、结构拆分至多个文件 2. 将方法的声明与定义隔开
when 筛选条件
where 泛型类型约束
value set访问器的输入参数值
yield 定义迭代器。返回类型必须是IEnumerable,IEnumerator

C# async声明函数代码块会执行await操作。

await标记:操作会在后台进行,此时先让权(yield),待此操作结束后,继续执行其后代码。

await标记的操作,通常是耗时的操作,如IO处理、CPU大量运算等。

在C#中,异步通过Task实现。async只是修饰符,可修饰任何函数;但await必定等待的是Task对象。

这种通常在其他语言里如Javascript中,实现为FuturePromise,即保证未来执行。也即让权,然后执行完后夺权。

编程指南:

  • 用using子句,替代try-finally语句

    Font font1 = new Font();
    try {
        byte charset = font1.charset;
    }finally{
        if (font1 != null) {
            ((IDispose)font1).Dispose();
        }
    }
      
    using(Font font1 = new Font) {
        byte charset = font1.charset;
    }
    
  • 使用对象初始设定项简化对象创建:

    var ins = new ExampleClass{Name = "Desktop",ID=3773,Age = 24};
    
  • 如果定义稍后不删事件处理,使用lambda

    public Form() {
        this.Click += (s,e) {
          MessageBox.show(
              (MouseEventArgs)e).Location.ToString()));
        }
    }
      
    // 原始:
    public Form() {
        this.Click += new EventHandler(Form1Click);
    }
    void Form1Click(object s,EventArgs e) {
          MessageBox.show(
              (MouseEventArgs)e).Location.ToString()));
    }
      
    

    C#

术语:

  • 类型Type/Class:数据类型,通常由:数据、方法集组成。类似于蓝图,指定该类型可以进行哪些操作。
  • 对象Instance/Object:类型的实例,可存储再命名变量、数组或集合中。
  • 结构Struct:单纯进行数据布局。

  • 语句Statement:单行代码,或{}包含的代码块。

  • 表达式Expression:表达式是由一个或多个操作数以及零个或多个运算符组成的序列,其计算结果为一个值、对象、方法或命名空间。 表达式可以包含文本值、方法调用、运算符及其操作数,或简单名称。 简单名称可以是变量名、类型成员名、方法参数名、命名空间名或类型名。 表达式可以使用运算符(运算符又可使用其他表达式作为参数)或方法调用(方法调用的参数又可以是其他方法调用),因此表达式可以非常简单,也可以极其复杂。
  • 字段Field:成员变量。字段分静态字段和实例字段。
  • 属性Property: 是访问器(get,set)的特殊方法。似字段,但是get,set方法集合。

Delegate:委托,函数类型

delegate 修饰后面的函数签名,定义函数类型。委托可理解为特定逻辑的执行,交给了其他函数来执行。

delegate TResult Func<in T,out TResult>(T arg);
delegate void Action<in T>(T obj);
delegate bool Predicate<in T>(T obj);

C#内置委托类型:

  • Func<>: 通常用于将委托参数转换成其他结果时。
  • Action<>:用于需要使用委托参数执行操作的情况。
  • Predicate<>:用于需要确定参数是否满足委托条件的情况。

c#支持匿名委托:

var result = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 }
            .FindAll(delegate (int no)
                     {
                         return (no % 2 == 0);
                     });

匿名委托也可写成lambda表达式:

var result = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 }
            .FindAll(i => i % 2 == 0);

Event: 事件

事件基于委托模型。委托模型遵守观察者设计模式,使订阅者能够向提供方注册并接收相关通知。 事件发送方推送事件发生的通知,事件接收器接收该通知并定义对它的响应。

异步

异步代码的特点:

  • 等待 I/O 请求返回的同时,可通过生成处理更多请求的线程,处理更多的服务器请求。
  • 等待 I/O 请求的同时生成 UI 交互线程,并通过将长时间运行的工作转换到其他 CPU 核心,让 UI 的响应速度更快。

C#中推荐使用基于任务的异步模型(还有基于事件的异步,不推荐),使用async/await关键字,以Task(任务)为基础,实现基于Promise(future,delay,deferred)的异步模型。即,承诺此操作会被执行。

每个异步操作,都会生成Task对象,Task对象可由c#内部管理的线程池分配线程进行工作。

async 声明此函数是异步操作函数;await将任务添加到线程池去工作。

平台调用

[DllImport("user32.dll")]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, int options);

MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);

常见库

数字:

using System.Numerics;

Vector2,Vector3,Vector4,
Matrix3x2,Matrix4x4,
Plane,
Quaternion,
Vector<T>

日期和时间:

DateTime.Now;
DateTime.Today;
DateTime.UtcNow;

TimeZone,TimeZoneInfo,TimeZoneOffset

集合和数据结构:

using System.Collections;	// 非泛型集合
using System.Collections.Generic;	// 泛型集合
using System.Collections.Concurrent; // 线程安全集合

interface IEnumerable<out T>; // 可枚举集合

    
我要…… 泛型集合选项 非泛型集合选项 线程安全或不可变集合选项
将项存储为键/值对以通过键进行快速查找 Dictionary Hashtable (根据键的哈希代码组织的键/值对的集合。) ConcurrentDictionary ReadOnlyDictionary ImmutableDictionary
按索引访问项 List Array ArrayList ImmutableList ImmutableArray
使用项先进先出 (FIFO) Queue Queue ConcurrentQueue ImmutableQueue
使用数据后进先出 (LIFO) Stack Stack ConcurrentStack ImmutableStack
按顺序访问项 LinkedList 无建议 无建议
删除集合中的项或向集合添加项时接收通知。(实现 INotifyPropertyChangedINotifyCollectionChanged ObservableCollection 无建议 无建议
已排序的集合 SortedList SortedList ImmutableSortedDictionary ImmutableSortedSet
数学函数的一个集 HashSet SortedSet 无建议 ImmutableHashSet ImmutableSortedSet

文件和流式IO

文件和目录:

using System.IO;

  • File - 提供用于创建、复制、删除、移动和打开文件的静态方法,并可帮助创建 FileStream 对象。
  • FileInfo - 提供用于创建、复制、删除、移动和打开文件的实例方法,并可帮助创建 FileStream 对象。
  • Directory - 提供用于创建、移动和枚举目录和子目录的静态方法。
  • DirectoryInfo - 提供用于创建、移动和枚举目录和子目录的实例方法。
  • Path - 提供用于以跨平台的方式处理目录字符串的方法和属性。

  • FileStream - 用于对文件进行读取和写入操作。
  • IsolatedStorageFileStream - 用于对独立存储中的文件进行读取或写入操作。
  • MemoryStream - 用于作为后备存储对内存进行读取和写入操作。
  • BufferedStream - 用于改进读取和写入操作的性能。
  • NetworkStream - 用于通过网络套接字进行读取和写入。
  • PipeStream - 用于通过匿名和命名管道进行读取和写入。
  • CryptoStream - 用于将数据流链接到加密转换。

读取器和编写器

System.IO 命名空间还提供用于在流中读取和写入已编码字符的类型。 通常,流用于字节输入和输出。 读取器和编写器类型处理编码字符与字节之间的来回转换,以便流可以完成操作。 每个读取器和编写器类都与流关联,可以通过类的 BaseStream 属性进行检索。

  • BinaryReaderBinaryWriter - 用于将基元数据类型作为二进制值进行读取和写入。
  • StreamReaderStreamWriter - 用于通过使用编码值在字符和字节之间来回转换来读取和写入字符。
  • StringReaderStringWriter - 用于从字符串读取字符以及将字符写入字符串中。
  • TextReaderTextWriter - 用作其他读取器和编写器(读取和写入字符和字符串,而不是二进制数据)的抽象基类。

压缩

压缩是指减小文件大小以便存储的过程。 解压缩是提取压缩文件的内容以使这些内容采用可用格式的过程。 System.IO.Compression 命名空间包含用于对文件和流进行压缩或解压缩的类型。

  • ZipArchive - 用于在 zip 存档中创建和检索条目。

  • ZipArchiveEntry - 用于表示压缩文件。

  • ZipFile - 用于创建、提取和打开压缩包。

  • ZipFileExtensions - 用于创建和提供压缩包中的条目。

  • DeflateStream - 用于使用 Deflate 算法对流进行压缩和解压缩。

  • GZipStream - 用于采用 gzip 数据格式对流进行压缩和解压缩。

独立存储

独立存储是一种数据存储机制,它在代码与保存的数据之间定义了标准化的关联方式,从而提供隔离性和安全性。 存储提供按用户、程序集和(可选)域隔离的虚拟文件系统。 当你的应用程序无权访问用户文件时,独立存储特别有用。 你可以通过一种由计算机的安全策略控制的方式保存应用程序的设置或文件。

全球化

using System.Globalization;
using System.Resources;
using System.Text;
		

批注属性(System.Attribute)

批注描述如何将数据序列化、指定用于强制安全性的特征并限制通过实时 (JIT) 编译器进行优化,从而使代码易于调试。 批注还可记录文件的名称或代码的作者,或控制窗体开发过程中控件和成员的可见性。

扩展方法

public static class StringExtension{
    public static int WordCount(this String str) // this不能省略
    {
        return str
            .Split(new char[] {' ', '.','?'}, StringSplitOptions.RemoveEmptyEntries)
            .Length;
    }
}

string s = "The quick brown fox jumped over the lazy dog.";
s.WordCount();

Regex:

@"mesh_([a-z]+)_([a-z]+)(_(\S+))" 匹配 mesh_body_bazzi_arib 
match.Groups5个,
第一个为字符串本身
依次匹配2,3
第四个为 _arib,
第五个为 "arib"
最近的文章

编程语言-Javascript编码规范

命名规范 当我们为变量, 函数和实例命名时, 使用 camelCase 命名法. // bad var FOOBar = {}; var foo_bar = {}; function FOOBar () {} // good var fooBar = {}; function fooBar () {} 当我们为类或者模块命名时, 使用 PascalCase 命名法. // bad var foobar = cc.Class({ f...…

继续阅读
更早的文章

笔记集锦-Rust

Rust 开发笔记rustup中国源: 清华大学开源镜像站 中科大 阿里云使用rustup安装rust时:$ # for bash$ RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustup rustup install stable # for stable$ # for fish$ env RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustu...…

继续阅读