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中,实现为Future
和Promise
,即保证未来执行。也即让权,然后执行完后夺权。
编程指南:
-
用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 | 无建议 | 无建议 |
删除集合中的项或向集合添加项时接收通知。(实现 INotifyPropertyChanged 和 INotifyCollectionChanged) | 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
属性进行检索。
- BinaryReader 和 BinaryWriter - 用于将基元数据类型作为二进制值进行读取和写入。
- StreamReader 和 StreamWriter - 用于通过使用编码值在字符和字节之间来回转换来读取和写入字符。
- StringReader 和 StringWriter - 用于从字符串读取字符以及将字符写入字符串中。
- TextReader 和 TextWriter - 用作其他读取器和编写器(读取和写入字符和字符串,而不是二进制数据)的抽象基类。
压缩
压缩是指减小文件大小以便存储的过程。 解压缩是提取压缩文件的内容以使这些内容采用可用格式的过程。 System.IO.Compression 命名空间包含用于对文件和流进行压缩或解压缩的类型。
-
ZipArchive - 用于在 zip 存档中创建和检索条目。
-
ZipArchiveEntry - 用于表示压缩文件。
-
ZipFile - 用于创建、提取和打开压缩包。
-
ZipFileExtensions - 用于创建和提供压缩包中的条目。
-
DeflateStream - 用于使用 Deflate 算法对流进行压缩和解压缩。
-
GZipStream - 用于采用 gzip 数据格式对流进行压缩和解压缩。
独立存储
独立存储是一种数据存储机制,它在代码与保存的数据之间定义了标准化的关联方式,从而提供隔离性和安全性。 存储提供按用户、程序集和(可选)域隔离的虚拟文件系统。 当你的应用程序无权访问用户文件时,独立存储特别有用。 你可以通过一种由计算机的安全策略控制的方式保存应用程序的设置或文件。
- IsolatedStorage - 提供用于独立存储实现的基类。
- IsolatedStorageFile - 提供包含文件和目录的独立存储区。
- IsolatedStorageFileStream - 公开独立存储中的文件。
全球化
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.Groups有5个,
第一个为字符串本身
依次匹配2,3,
第四个为 _arib,
第五个为 "arib"