zoukankan      html  css  js  c++  java
  • 学习笔记之C# 教程 | 菜鸟教程

    C# 教程 | 菜鸟教程

    http://www.runoob.com/csharp/csharp-tutorial.html

    菜鸟教程在线编辑器

    http://www.runoob.com/try/runcode.php?filename=HelloWorld&type=cs

    • C# Programming Guide - 介绍了有关关键的 C# 语言特征以及如何通过 .NET 框架访问 C# 的详细信息。
    • Visual Studio - 下载作为 C# 集成开发环境的 Visual Studio 的最新版本。
    • Go Mono - Mono 是一个允许开发人员简单地创建跨平台应用程序的软件平台。
    • C Sharp (programming language) - 维基百科解释 C#(编程语言)。
    • C# 一些重要的功能:在 C# 中,变量分为以下几种类型:值类型(Value types)/ 引用类型(Reference types)/ 指针类型(Pointer types)值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。值类型直接包含数据。比如 int、char、float,它们分别存储数字、字母、浮点数。当您声明一个 int 类型时,系统分配内存来存储值。如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用 sizeof 方法。表达式 sizeof(type) 产生以字节为单位存储对象或类型的存储尺寸。引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、dynamic 和 string。对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中所有数据类型的终极基类。Object 是 System.Object 类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先进行类型转换。当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
      • 布尔条件(Boolean Conditions)
      • 自动垃圾回收(Automatic Garbage Collection)
      • 标准库(Standard Library)
      • 组件版本(Assembly Versioning)
      • 属性(Properties)和事件(Events)
      • 委托(Delegates)和事件管理(Events Management)
      • 易于使用的泛型(Generics)
      • 索引器(Indexers)
      • 条件编译(Conditional Compilation)
      • 简单的多线程(Multithreading)
      • LINQ 和 Lambda 表达式
      • 集成 Windows
    • 您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
    • 动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
    • 字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String 类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和 @引号。
    • C# string 字符串的前面可以加 @(称作"逐字字符串")将转义字符()当作普通字符对待
    • @ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。
    • 用户自定义引用类型有:class、interface 或 delegate。
    • 指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
    • 类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。在 C# 中,类型铸造有两种形式:
      • 隐式类型转换 - 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
      • 显式类型转换 - 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失。
    • C# 提供了下列内置的类型转换方法:C# 中提供的基本的值类型:空类型 可为空值的数据类型C# 允许定义其他值类型的变量,比如 enum,也允许定义引用类型变量,比如 class。System 命名空间中的 Console 类提供了一个函数 ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中。函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。
      • ToBoolean 如果可能的话,把类型转换为布尔型。
      • ToByte 把类型转换为字节类型。
      • ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型。
      • ToDateTime 把类型(整数或字符串类型)转换为 日期-时间 结构。
      • ToDecimal 把浮点型或整数类型转换为十进制类型。
      • ToDouble 把类型转换为双精度浮点型。
      • ToInt16 把类型转换为 16 位整数类型。
      • ToInt32 把类型转换为 32 位整数类型。
      • ToInt64 把类型转换为 64 位整数类型。
      • ToSbyte 把类型转换为有符号字节类型。
      • ToSingle 把类型转换为小浮点数类型。
      • ToString 把类型转换为字符串类型。
      • ToType 把类型转换为指定类型。
      • ToUInt16 把类型转换为 16 位无符号整数类型。
      • ToUInt32 把类型转换为 32 位无符号整数类型。
      • ToUInt64 把类型转换为 64 位无符号整数类型。
    • 整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。
    • 一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。使用小数形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。
    • 字符常量是括在单引号里,例如,'x',且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 'x')、一个转义序列(例如 ' ')或者一个通用字符(例如 'u02C0')。在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符( )或制表符 tab( )。
    • 字符常量是括在双引号 "" 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。
    • C# 支持的其他一些重要的运算符您可以把一个 switch 作为一个外部 switch 的语句序列的一部分,即可以在一个 switch 语句内使用另一个 switch 语句。即使内部和外部 switch 的 case 常量包含共同的值,也没有矛盾。 C# 也支持 foreach 循环,使用foreach可以迭代数组或者一个集合对象。抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化,封装则使开发者实现所需级别的抽象。
      • sizeof() 返回数据类型的大小。 sizeof(int),将返回 4.
      • typeof() 返回 class 的类型。 typeof(StreamReader);
      • is 判断对象是否为某一类型。 If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。
      • as 强制转换,即使转换失败也不会抛出异常。 Object obj = new StringReader("Hello"); StringReader r = obj as StringReader;
    • C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现。一个 访问修饰符 定义了一个类成员的范围和可见性。C# 支持的访问修饰符如下所示:Internal 访问说明符允许一个类将其成员变量和成员函数暴露给当前程序中的其他函数和对象。换句话说,带有 internal 访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问。如果没有指定访问修饰符,则使用类成员的默认访问修饰符,即为 private。Protected Internal 访问修饰符允许在本类,派生类或者包含该类的程序集中访问。这也被用于实现继承。一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。每一个 C# 程序至少有一个带有 Main 方法的类。
      • public:所有对象都可以访问;
      • private:对象本身在对象内部可以访问;
      • protected:只有该类对象及其子类对象可以访问
      • internal:同一个程序集的对象可以访问;
      • protected internal:访问限于当前程序集或派生自包含类的类型。
    • 方法的元素:Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
    • 您可以使用方法名调用方法。您也可以使用类的实例从另一个类中调用其他类的公有方法。
    • 引用参数是一个对变量的内存位置的引用。在 C# 中,使用 ref 关键字声明引用参数。
    • C# 提供了一个特殊的数据类型,nullable 类型(可空类型),可空类型可以表示其基础值类型正常范围内的值,再加上一个 null 值。< data_type> ? <variable_name> = null;
    • Null 合并运算符用于定义可空类型和引用类型的默认值。Null 合并运算符为类型转换定义了一个预设值,以防可空类型的值为 Null。Null 合并运算符把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型。如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。
    • 声明一个数组不会在内存中初始化数组。当初始化数组变量时,您可以赋值给数组。数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例:double[] balance = new double[10];
    • 您也可以赋值一个数组变量到另一个目标数组变量中。在这种情况下,目标和源会指向相同的内存位置
    • 当您创建一个数组时,C# 编译器会根据数组类型隐式初始化每个数组元素为一个默认值。例如,int 数组的所有元素都会被初始化为 0。
    • 您可以声明一个 string 变量的二维数组,如下:string [,] names;
    • 交错数组是数组的数组。您可以声明一个带有 int 值的交错数组 scores,如下所示:int [][] scores;
    • 有时,当声明一个方法时,您不能确定要传递给函数作为参数的参数数目。C# 参数数组解决了这个问题,参数数组通常用于传递未知数量的参数给函数。在使用数组作为形参时,C# 提供了 params 关键字,使调用数组为形参的方法时,既可以传递数组实参,也可以只传递一组数组。params 的使用格式为:public 返回类型 方法名称( params 类型名称[] 数组名称 )
    • Array 类是 C# 中所有数组的基类,它是在 System 命名空间中定义。Array 类提供了各种用于数组的属性和方法。
    • Array 类中一些最常用的属性:
      • IsFixedSize 获取一个值,该值指示数组是否带有固定大小。
      • IsReadOnly 获取一个值,该值指示数组是否只读。
      • Length 获取一个 32 位整数,该值表示所有维度的数组中的元素总数。
      • LongLength 获取一个 64 位整数,该值表示所有维度的数组中的元素总数。
      • Rank 获取数组的秩(维度)。
    • Array 类中一些最常用的方法:在 C# 中,您可以使用字符数组来表示字符串,但是,更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字是 System.String 类的别名。
      • Clear 根据元素的类型,设置数组中某个范围的元素为零、为 false 或者为 null。
      • Copy(Array, Array, Int32) 从数组的第一个元素开始复制某个范围的元素到另一个数组的第一个元素位置。长度由一个 32 位整数指定。
      • CopyTo(Array, Int32) 从当前的一维数组中复制所有的元素到一个指定的一维数组的指定索引位置。索引由一个 32 位整数指定。
      • GetLength 获取一个 32 位整数,该值表示指定维度的数组中的元素总数。
      • GetLongLength 获取一个 64 位整数,该值表示指定维度的数组中的元素总数。
      • GetLowerBound 获取数组中指定维度的下界。
      • GetType 获取当前实例的类型。从对象(Object)继承。
      • GetUpperBound 获取数组中指定维度的上界。
      • GetValue(Int32) 获取一维数组中指定位置的值。索引由一个 32 位整数指定。
      • IndexOf(Array, Object) 搜索指定的对象,返回整个一维数组中第一次出现的索引。
      • Reverse(Array) 逆转整个一维数组中元素的顺序。
      • SetValue(Object, Int32) 给一维数组中指定位置的元素设置值。索引由一个 32 位整数指定。
      • Sort(Array) 使用数组的每个元素的 IComparable 实现来排序整个一维数组中的元素。
      • ToString 返回一个表示当前对象的字符串。从对象(Object)继承。
    • 您可以使用以下方法之一来创建 string 对象:
      • 通过给 String 变量指定一个字符串
      • 通过使用 String 类构造函数
      • 通过使用字符串串联运算符( + )
      • 通过检索属性或调用一个返回字符串的方法
      • 通过格式化方法来转换一个值或对象为它的字符串表示形式
    • String 类有以下两个属性:
      • Chars 在当前 String 对象中获取 Char 对象的指定位置。
      • Length 在当前的 String 对象中获取字符数。
    • String 类有许多方法用于 string 对象的操作。下面的表格提供了一些最常用的方法:在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
      • public static int Compare( string strA, string strB ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。该方法区分大小写。
      • public static int Compare( string strA, string strB, bool ignoreCase ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。但是,如果布尔参数为真时,该方法不区分大小写。
      • public static string Concat( string str0, string str1 ) 连接两个 string 对象。
      • public static string Concat( string str0, string str1, string str2 ) 连接三个 string 对象。
      • public static string Concat( string str0, string str1, string str2, string str3 ) 连接四个 string 对象。
      • public bool Contains( string value ) 返回一个表示指定 string 对象是否出现在字符串中的值。
      • public static string Copy( string str ) 创建一个与指定字符串具有相同值的新的 String 对象。
      • public void CopyTo( int sourceIndex, char[] destination, int destinationIndex, int count ) 从 string 对象的指定位置开始复制指定数量的字符到 Unicode 字符数组中的指定位置。
      • public bool EndsWith( string value ) 判断 string 对象的结尾是否匹配指定的字符串。
      • public bool Equals( string value ) 判断当前的 string 对象是否与指定的 string 对象具有相同的值。
      • public static bool Equals( string a, string b ) 判断两个指定的 string 对象是否具有相同的值。
      • public static string Format( string format, Object arg0 ) 把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。
      • public int IndexOf( char value ) 返回指定 Unicode 字符在当前字符串中第一次出现的索引,索引从 0 开始。
      • public int IndexOf( string value ) 返回指定字符串在该实例中第一次出现的索引,索引从 0 开始。
      • public int IndexOf( char value, int startIndex ) 返回指定 Unicode 字符从该字符串中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
      • public int IndexOf( string value, int startIndex ) 返回指定字符串从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
      • public int IndexOfAny( char[] anyOf ) 返回某一个指定的 Unicode 字符数组中任意字符在该实例中第一次出现的索引,索引从 0 开始。
      • public int IndexOfAny( char[] anyOf, int startIndex ) 返回某一个指定的 Unicode 字符数组中任意字符从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
      • public string Insert( int startIndex, string value ) 返回一个新的字符串,其中,指定的字符串被插入在当前 string 对象的指定索引位置。
      • public static bool IsNullOrEmpty( string value ) 指示指定的字符串是否为 null 或者是否为一个空的字符串。
      • public static string Join( string separator, string[] value ) 连接一个字符串数组中的所有元素,使用指定的分隔符分隔每个元素。
      • public static string Join( string separator, string[] value, int startIndex, int count ) 连接接一个字符串数组中的指定位置开始的指定元素,使用指定的分隔符分隔每个元素。
      • public int LastIndexOf( char value ) 返回指定 Unicode 字符在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
      • public int LastIndexOf( string value ) 返回指定字符串在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
      • public string Remove( int startIndex ) 移除当前实例中的所有字符,从指定位置开始,一直到最后一个位置为止,并返回字符串。
      • public string Remove( int startIndex, int count ) 从当前字符串的指定位置开始移除指定数量的字符,并返回字符串。
      • public string Replace( char oldChar, char newChar ) 把当前 string 对象中,所有指定的 Unicode 字符替换为另一个指定的 Unicode 字符,并返回新的字符串。
      • public string Replace( string oldValue, string newValue ) 把当前 string 对象中,所有指定的字符串替换为另一个指定的字符串,并返回新的字符串。
      • public string[] Split( params char[] separator ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。
      • public string[] Split( char[] separator, int count ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。int 参数指定要返回的子字符串的最大数目。
      • public bool StartsWith( string value ) 判断字符串实例的开头是否匹配指定的字符串。
      • public char[] ToCharArray() 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组。
      • public char[] ToCharArray( int startIndex, int length ) 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组,从指定的索引开始,直到指定的长度为止。
      • public string ToLower() 把字符串转换为小写并返回。
      • public string ToUpper() 把字符串转换为大写并返回。
      • public string Trim() 移除当前 String 对象中的所有前导空白字符和后置空白字符。
    • 在 C# 中的结构与传统的 C 或 C++ 中的结构不同。C# 中的结构有以下特点:
      • 结构可带有方法、字段、索引、属性、运算符方法和事件。
      • 结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义默认的构造函数。默认的构造函数是自动定义的,且不能被改变。
      • 与类不同,结构不能继承其他的结构或类。
      • 结构不能作为其他结构或类的基础结构。
      • 结构可实现一个或多个接口。
      • 结构成员不能指定为 abstract、virtual 或 protected。
      • 当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
      • 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
    • 类和结构有以下几个基本的不同点:枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。C# 枚举是值数据类型。换句话说,枚举包含自己的值,且不能继承或传递继承。枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0.类的默认访问标识符是 internal,成员的默认访问标识符是 private。类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。构造函数的名称与类的名称完全相同,它没有任何返回类型。
      • 类是引用类型,结构是值类型。
      • 结构不支持继承。
      • 结构不能声明默认的构造函数。
    • 类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
    • 我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取。静态变量可在成员函数或类的定义外部进行初始化。你也可以在类的定义内部初始化静态变量。
    • 你也可以把一个成员函数声明为 static。这样的函数只能访问静态变量。静态函数在对象被创建之前就已经存在。
    • 多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。C# 不支持多重继承。但是,您可以使用接口来实现多重继承。
    • 子类可以直接调用父类中的方法,父类想要调用子类中的方法可以把子类对象赋值给父类类型的变量
    • 多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
    • 在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:函数重载 / 运算符重载
    • 您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
    • C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。请注意,下面是有关抽象类的一些规则:当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
      • 您不能创建一个抽象类的实例。
      • 您不能在一个抽象类外部声明一个抽象方法。
      • 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
    • 动态多态性是通过 抽象类 和 虚方法 实现的。
    • 您可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
    • 下表描述了 C# 中运算符重载的能力:
    运算符描述
    +, -, !, ~, ++, -- 这些一元运算符只有一个操作数,且可以被重载。
    +, -, *, /, % 这些二元运算符带有两个操作数,且可以被重载。
    ==, !=, <, >, <=, >= 这些比较运算符可以被重载。
    &&, || 这些条件逻辑运算符不能被直接重载。
    +=, -=, *=, /=, %= 这些赋值运算符不能被重载。
    =, ., ?:, ->, new, is, sizeof, typeof 这些运算符不能被重载。
     
    • 接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做" 部分。接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。接口使得实现接口的类或结构在形式上保持一致。抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时
    • 接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。
    • 通常接口命令以 I 字母开头
    • 命名空间的设计目的是提供一种让一组名称与其他名称分隔开的方式。在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突。
    • 命名空间的定义是以关键字 namespace 开始,后跟命名空间的名称。为了调用支持命名空间版本的函数或变量,会把命名空间的名称置于前面
    • using 关键字表明程序使用的是给定命名空间中的名称。
    • 您也可以使用 using 命名空间指令,这样在使用的时候就不用在前面加上命名空间名称。该指令告诉编译器随后的代码使用了指定命名空间中的名称。
    • 命名空间可以被嵌套,即您可以在一个命名空间内定义另一个命名空间。您可以使用点(.)运算符访问嵌套的命名空间的成员
    • 预处理器指令指导编译器在实际编译开始之前对信息进行预处理。所有的预处理器指令都是以 # 开始。且在一行上,只有空白字符可以出现在预处理器指令之前。预处理器指令不是语句,所以它们不以分号(;)结束。C# 编译器没有一个单独的预处理器,但是,指令被处理时就像是有一个单独的预处理器一样。在 C# 中,预处理器指令用于在条件编译中起作用。与 C 和 C++ 不同的是,它们不是用来创建宏。一个预处理器指令必须是该行上的唯一指令。
    • 下表列出了 C# 中可用的预处理器指令:
    预处理器指令描述
    #define 它用于定义一系列成为符号的字符。
    #undef 它用于取消定义符号。
    #if 它用于测试符号是否为真。
    #else 它用于创建复合条件指令,与 #if 一起使用。
    #elif 它用于创建复合条件指令。
    #endif 指定一个条件指令的结束。
    #line 它可以让您修改编译器的行数以及(可选地)输出错误和警告的文件名。
    #error 它允许从代码的指定位置生成一个错误。
    #warning 它允许从代码的指定位置生成一级警告。
    #region 它可以让您在使用 Visual Studio Code Editor 的大纲特性时,指定一个可展开或折叠的代码块。
    #endregion 它标识着 #region 块的结束。
    • #define 预处理器指令创建符号常量。#define 允许您定义一个符号,这样,通过使用符号作为传递给 #if 指令的表达式,表达式将返回 true。
    • 您可以使用 #if 指令来创建一个条件指令。条件指令用于测试符号是否为真。如果为真,编译器会执行 #if 和下一个指令之间的代码。
    • 条件指令用于在调试版本或编译指定配置时编译代码。一个以 #if 指令开始的条件指令,必须显示地以一个 #endif 指令终止。
    • 正则表达式 是一种匹配输入文本的模式。.Net 框架提供了允许这种匹配的正则表达式引擎。模式由一个或多个字符、运算符和结构组成。
    • 下面列出了用于定义正则表达式的各种类别的字符、运算符和结构:字符转义 / 字符类 / 定位点 / 分组构造 / 限定符 / 反向引用构造 / 备用构造 / 替换 / 杂项构造
    • 正则表达式中的反斜杠字符()指示其后跟的字符是特殊字符,或应按原义解释该字符。
    • 字符类与一组字符中的任何一个字符匹配。下表列出了字符类:
    字符类描述模式匹配
    [character_group] 匹配 character_group 中的任何单个字符。 默认情况下,匹配区分大小写。 [mn] "mat" 中的 "m","moon" 中的 "m" 和 "n"
    [^character_group] 非:与不在 character_group 中的任何单个字符匹配。 默认情况下,character_group 中的字符区分大小写。 [^aei] "avail" 中的 "v" 和 "l"
    [ first - last ] 字符范围:与从 first 到 last 的范围中的任何单个字符匹配。 (w+) "Name Addr " 中的 "Name " 和 "Addr "
    . 通配符:与除 之外的任何单个字符匹配。
    若要匹配原意句点字符(. 或 u002E),您必须在该字符前面加上转义符 (.)。
    a.e "have" 中的 "ave", "mate" 中的 "ate"
    p{ name } 与 name 指定的 Unicode 通用类别或命名块中的任何单个字符匹配。 p{Lu} "City Lights" 中的 "C" 和 "L"
    P{ name } 与不在 name 指定的 Unicode 通用类别或命名块中的任何单个字符匹配。 P{Lu} "City" 中的 "i"、 "t" 和 "y"
    w 与任何单词字符匹配。 w "Room#1" 中的 "R"、 "o"、 "m" 和 "1"
    W 与任何非单词字符匹配。 W "Room#1" 中的 "#"
    s 与任何空白字符匹配。 ws "ID A1.3" 中的 "D "
    S 与任何非空白字符匹配。 sS "int __ctr" 中的 " _"
    d 与任何十进制数字匹配。 d "4 = IV" 中的 "4"
    D 匹配不是十进制数的任意字符。 D "4 = IV" 中的 " "、 "="、 " "、 "I" 和 "V"
    • 定位点或原子零宽度断言会使匹配成功或失败,具体取决于字符串中的当前位置,但它们不会使引擎在字符串中前进或使用字符。下表列出了定位点:
    断言描述模式匹配
    ^ 匹配必须从字符串或一行的开头开始。 ^d{3} "567-777-" 中的 "567"
    $ 匹配必须出现在字符串的末尾或出现在行或字符串末尾的   之前。 -d{4}$ "8-12-2012" 中的 "-2012"
    A 匹配必须出现在字符串的开头。 Aw{4} "Code-007-" 中的 "Code"
     匹配必须出现在字符串的末尾或出现在字符串末尾的   之前。 -d{3} "Bond-901-007" 中的 "-007"
    z 匹配必须出现在字符串的末尾。 -d{3}z "-901-333" 中的 "-333"
    G 匹配必须出现在上一个匹配结束的地方。 G(d) "(1)(3)(5)[7](9)" 中的 "(1)"、 "(3)" 和 "(5)"
     匹配一个单词边界,也就是指单词和空格间的位置。 er 匹配"never"中的"er",但不能匹配"verb"中的"er"。
    B 匹配非单词边界。 erB 匹配"verb"中的"er",但不能匹配"never"中的"er"。
    • 分组构造描述了正则表达式的子表达式,通常用于捕获输入字符串的子字符串。下表列出了分组构造:
    分组构造描述模式匹配
    ( subexpression ) 捕获匹配的子表达式并将其分配到一个从零开始的序号中。 (w)1 "deep" 中的 "ee"
    (?< name >subexpression) 将匹配的子表达式捕获到一个命名组中。 (?< double>w)k< double> "deep" 中的 "ee"
    (?< name1 -name2 >subexpression) 定义平衡组定义。 (((?'Open'()[^()]*)+((?'Close-Open'))[^()]*)+)*(?(Open)(?!))$ "3+2^((1-3)*(3-1))" 中的 "((1-3)*(3-1))"
    (?: subexpression) 定义非捕获组。 Write(?:Line)? "Console.WriteLine()" 中的 "WriteLine"
    (?imnsx-imnsx:subexpression) 应用或禁用 subexpression 中指定的选项。  Ad{2}(?i:w+) "A12xl A12XL a12xl" 中的 "A12xl" 和 "A12XL" 
    (?= subexpression) 零宽度正预测先行断言。 w+(?=.) "He is. The dog ran. The sun is out." 中的 "is"、 "ran" 和 "out"
    (?! subexpression) 零宽度负预测先行断言。 (?!un)w+ "unsure sure unity used" 中的 "sure" 和 "used"
    (?<=subexpression) 零宽度正回顾后发断言。 (?<=19)d{2} "1851 1999 1950 1905 2003" 中的 "99"、"50"和 "05"
    (?<! subexpression) 零宽度负回顾后发断言。 (? "Hi woman Hi man" 中的 "man"
    (?> subexpression) 非回溯(也称为"贪婪")子表达式。 [13579](?>A+B+) "1ABB 3ABBC 5AB 5AC" 中的 "1ABB"、 "3ABB" 和 "5AB"
    •  限定符指定在输入字符串中必须存在上一个元素(可以是字符、组或字符类)的多少个实例才能出现匹配项。 限定符包括下表中列出的语言元素。下表列出了限定符:
    限定符描述模式匹配
    * 匹配上一个元素零次或多次。 d*.d ".0"、 "19.9"、 "219.9"
    + 匹配上一个元素一次或多次。 "be+" "been" 中的 "bee", "bent" 中的 "be"
    ? 匹配上一个元素零次或一次。 "rai?n" "ran"、 "rain"
    { n } 匹配上一个元素恰好 n 次。 ",d{3}" "1,043.6" 中的 ",043", "9,876,543,210" 中的 ",876"、 ",543" 和 ",210"
    { n ,} 匹配上一个元素至少 n 次。 "d{2,}" "166"、 "29"、 "1930"
    { n , m } 匹配上一个元素至少 n 次,但不多于 m 次。 "d{3,5}" "166", "17668", "193024" 中的 "19302"
    *? 匹配上一个元素零次或多次,但次数尽可能少。 d*?.d ".0"、 "19.9"、 "219.9"
    +? 匹配上一个元素一次或多次,但次数尽可能少。 "be+?" "been" 中的 "be", "bent" 中的 "be"
    ?? 匹配上一个元素零次或一次,但次数尽可能少。 "rai??n" "ran"、 "rain"
    { n }? 匹配前导元素恰好 n 次。 ",d{3}?" "1,043.6" 中的 ",043", "9,876,543,210" 中的 ",876"、 ",543" 和 ",210"
    { n ,}? 匹配上一个元素至少 n 次,但次数尽可能少。 "d{2,}?" "166"、 "29" 和 "1930"
    { n , m }? 匹配上一个元素的次数介于 n 和 m 之间,但次数尽可能少。 "d{3,5}?" "166", "17668", "193024" 中的 "193" 和 "024"
    • 反向引用允许在同一正则表达式中随后标识以前匹配的子表达式。下表列出了反向引用构造:
    反向引用构造描述模式匹配
    number 反向引用。 匹配编号子表达式的值。 (w)1 "seek" 中的 "ee"
    k< name > 命名反向引用。 匹配命名表达式的值。 (?< char>w)k< char> "seek" 中的 "ee"
    • 备用构造用于修改正则表达式以启用 either/or 匹配。下表列出了备用构造:
    备用构造描述模式匹配
    | 匹配以竖线 (|) 字符分隔的任何一个元素。 th(e|is|at) "this is the day. " 中的 "the" 和 "this"
    (?( expression )yes | no ) 如果正则表达式模式由 expression 匹配指定,则匹配 yes;否则匹配可选的 no 部分。 expression 被解释为零宽度断言。 (?(A)Ad{2}|d{3}) "A10 C103 910" 中的 "A10" 和 "910"
    (?( name )yes | no ) 如果 name 或已命名或已编号的捕获组具有匹配,则匹配 yes;否则匹配可选的 no。 (?< quoted>")?(?(quoted).+?"|S+s) "Dogs.jpg "Yiska playing.jpg"" 中的 Dogs.jpg 和 "Yiska playing.jpg"
    • 替换是替换模式中使用的正则表达式。下表列出了用于替换的字符:
    字符描述模式替换模式输入字符串结果字符串
    $number 替换按组 number 匹配的子字符串。 (w+)(s)(w+) $3$2$1 "one two" "two one"
    ${name} 替换按命名组 name 匹配的子字符串。 (?< word1>w+)(s)(?< word2>w+) ${word2} ${word1} "one two" "two one"
    $$ 替换字符"$"。 (d+)s?USD $$$1 "103 USD" "$103"
    $& 替换整个匹配项的一个副本。 ($*(d*(.+d+)?){1}) **$& "$1.30" "**$1.30**"
    $` 替换匹配前的输入字符串的所有文本。 B+ $` "AABBCC" "AAAACC"
    $' 替换匹配后的输入字符串的所有文本。 B+ $' "AABBCC" "AACCCC"
    $+ 替换最后捕获的组。 B+(C+) $+ "AABBCCDD" AACCDD
    $_ 替换整个输入字符串。 B+ $_ "AABBCC" "AAAABBCCCC"
    • 下表列出了各种杂项构造:
    构造描述实例
    (?imnsx-imnsx) 在模式中间对诸如不区分大小写这样的选项进行设置或禁用。 A(?i)bw+ 匹配 "ABA Able Act" 中的 "ABA" 和 "Able"
    (?#注释) 内联注释。该注释在第一个右括号处终止。 A(?#匹配以A开头的单词)w+
    # [行尾] 该注释以非转义的 # 开头,并继续到行的结尾。 (?x)Aw+#匹配以 A 开头的单词
    • Regex 类用于表示一个正则表达式。下表列出了 Regex 类中一些常用的方法:
    序号方法 & 描述
    1 public bool IsMatch( string input ) 
    指示 Regex 构造函数中指定的正则表达式是否在指定的输入字符串中找到匹配项。
    2 public bool IsMatch( string input, int startat ) 
    指示 Regex 构造函数中指定的正则表达式是否在指定的输入字符串中找到匹配项,从字符串中指定的开始位置开始。
    3 public static bool IsMatch( string input, string pattern ) 
    指示指定的正则表达式是否在指定的输入字符串中找到匹配项。
    4 public MatchCollection Matches( string input ) 
    在指定的输入字符串中搜索正则表达式的所有匹配项。
    5 public string Replace( string input, string replacement ) 
    在指定的输入字符串中,把所有匹配正则表达式模式的所有匹配的字符串替换为指定的替换字符串。
    6 public string[] Split( string input ) 
    • 把输入字符串分割为子字符串数组,根据在 Regex 构造函数中指定的正则表达式模式定义的位置进行分割。
    • 异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应,比如尝试除以零。异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。
      • try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
      • catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
      • finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。例如,如果您打开一个文件,不管是否出现异常文件都要被关闭。
      • throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。
    • C# 异常是使用类来表示的。C# 中的异常类主要是直接或间接地派生于 System.Exception类。System.ApplicationException 和 System.SystemException 类是派生于 System.Exception 类的异常类。System.ApplicationException 类支持由应用程序生成的异常。所以程序员定义的异常都应派生自该类。System.SystemException 类是所有预定义的系统异常的基类。下表列出了一些派生自 Sytem.SystemException 类的预定义的异常类:

      异常类描述
      System.IO.IOException 处理 I/O 错误。
      System.IndexOutOfRangeException 处理当方法指向超出范围的数组索引时生成的错误。
      System.ArrayTypeMismatchException 处理当数组类型不匹配时生成的错误。
      System.NullReferenceException 处理当依从一个空对象时生成的错误。
      System.DivideByZeroException 处理当除以零时生成的错误。
      System.InvalidCastException 处理在类型转换期间生成的错误。
      System.OutOfMemoryException 处理空闲内存不足生成的错误。
      System.StackOverflowException 处理栈溢出生成的错误。
    • 您也可以定义自己的异常。用户自定义的异常类是派生自 ApplicationException 类。
    • 如果异常是直接或间接派生自 System.Exception 类,您可以抛出一个对象。您可以在 catch 块中使用 throw 语句来抛出当前的对象
    • 一个 文件 是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个 流。从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数据(写操作)。
    • System.IO 命名空间有各种不同的类,用于执行各种文件操作,如创建和删除文件、读取或写入文件,关闭文件等。下表列出了一些 System.IO 命名空间中常用的非抽象类:
    I/O 类描述
    BinaryReader 从二进制流读取原始数据。
    BinaryWriter 以二进制格式写入原始数据。
    BufferedStream 字节流的临时存储。
    Directory 有助于操作目录结构。
    DirectoryInfo 用于对目录执行操作。
    DriveInfo 提供驱动器的信息。
    File 有助于处理文件。
    FileInfo 用于对文件执行操作。
    FileStream 用于文件中任何位置的读写。
    MemoryStream 用于随机访问存储在内存中的数据流。
    Path 对路径信息执行操作。
    StreamReader 用于从字节流中读取字符。
    StreamWriter 用于向一个流中写入字符。
    StringReader 用于读取字符串缓冲区。
    StringWriter 用于写入字符串缓冲区。
    • System.IO 命名空间中的 FileStream 类有助于文件的读写与关闭。该类派生自抽象类 Stream。您需要创建一个 FileStream 对象来创建一个新的文件,或打开一个已有的文件。

    参数描述
    FileMode

    FileMode 枚举定义了各种打开文件的方法。FileMode 枚举的成员有:

    • Append:打开一个已有的文件,并将光标放置在文件的末尾。如果文件不存在,则创建文件。
    • Create:创建一个新的文件。如果文件已存在,则删除旧文件,然后创建新文件。
    • CreateNew:指定操作系统应创建一个新的文件。如果文件已存在,则抛出异常。
    • Open:打开一个已有的文件。如果文件不存在,则抛出异常。
    • OpenOrCreate:指定操作系统应打开一个已有的文件。如果文件不存在,则用指定的名称创建一个新的文件打开。
    • Truncate:打开一个已有的文件,文件一旦打开,就将被截断为零字节大小。然后我们可以向文件写入全新的数据,但是保留文件的初始创建日期。如果文件不存在,则抛出异常。
    FileAccess

    FileAccess 枚举的成员有:Read、ReadWrite 和 Write。

    FileShare

    FileShare 枚举的成员有:

    • Inheritable:允许文件句柄可由子进程继承。Win32 不直接支持此功能。
    • None:谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。 
    • Read:允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
    • ReadWrite:允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。 
    • Write:允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。 
    • Delete:允许随后删除文件。
     
  • 相关阅读:
    mkdir()和mkdirs() 的区别
    JAVA 多线程学习
    遇到问题(1)
    7.12计划
    Android 中Int类型和String类型的转换
    Android Binder机制学习笔记
    7.11计划,做个没心没肺的人
    RTL行为级仿真、综合后门级功能仿真和时序仿真
    定向锚文本(高级) 站内站策略(高级) 链轮模式(高级) 站群模式(高级)
    优化长尾关键词基础指南
  • 原文地址:https://www.cnblogs.com/pegasus923/p/8026075.html
Copyright © 2011-2022 走看看