标签:
使用Unicode转义序列可以指定Unicode 字符,该转义序列包括标准的\字符,后跟一个u和一个4位十六进制值(例如,单引号的unicode是0x0027)。下面的字符串是等价的:
"Karli\‘s string."
"Karli\u0027s string."
字符串之前加一个@字符, 即两个双引号之间的所有字符都包含在字符串中,包括行末字符和需要转义的字符。唯一例外是双引号字符的转义,它们必须指定,以免结束字符串。
using 语句还可以为名称空间提供一个别名。
1 namespace LevelOne 2 { 3 using LT = LevelTwo; 4 // name "NameThree" defined 5 namespace LevelTwo 6 { 7 // name "NameThree" defined 8 } 9 }
LevelOne名称空间中的代码可以把 LevelOne.NameThree 引用为NameThree , 把LevelOne.LevelTwo.NameThree 引用为LT.NameThree。
在C++中,可以在运行完一个 case 语句后,运行另一个 case 语句。C#不行,每一个分支中的代码最后必须要有一个break,除非多个case 语句放在一起:
switch(<testVar>) { case <comparisonVal1>: case <comparisonVal2>: <code to execute> break; ... }
string myString = "north"; Orientation myDirection = (Orientation)Enum.Pase(typeof(Orientation), myString);
foreach(string name in friendnames) { name = "Rupert the bear"; }
数组的数组(锯齿数组或者不定数组):如
int[][] jaggedIntArray;
初始化:
int[][] jaggedIntArray; jaggedIntArray = new int[2][]; jaggedIntArray[0] = new int[3]; jaggedIntArray[1] = new int[4];
或:
jaggedIntArray = new int[3][]{new int[]{1,2,3}, new int[]{1}, new int[]{1,2}};
或:
int[][] jaggedIntArray = {new int[]{1,2,3}, new int[]{1}, new int[]{1,2}};
对数组的数组(锯齿数组或者不定数组)可以使用foreach 循环,但如下使用会出错(普通二维等多维数组可以):有数组divisors1To10是不定数组:
foreach(int divisor in divisors1To10) { Console.WriteLine(divisor); }
因为数组divisors1To10 包含int[]元素,而不是int 元素。必须循环每个子数组和数组本身:
foreach(int[] divisorofInt in divisors1To10) { foreach(int divisor in divisorofInt) { Console.WriteLine(divisor); } }
函数传引用:ref,定义和使用时都得加ref:
static void ShowDouble(ref int val);
ShowDouble(ref myNumber);
输出参数:out,使用方式与 ref关键字相同(在函数定义和函数调用中用作参数的修饰符)。但注意:
1、把未赋值的变量用作ref参数是非法的,但可以把未赋值的变量用作out参数。
2、另外,在函数使用out参数时,out参数必须看作是还未赋值。
即调用代码可以把已赋值的变量用作out参数,存储在该变量中的值会在函数执行时丢失。输出调试信息: 在运行期间把文本写入“输出”(Output) 窗口。
1.Debug.WriteLine(),仅在调试模式下运行, 在发布版本中,该命令会消失
2.Trace.WriteLine() , 可用于发布程序
类似还有:
Debug.Write()
Trace.Write()
Debug.WriteLineIf()
Trace.WriteLineIf()
Debug.WriteIf()
Trace.WriteIf()
判定语句(assertion)时中断:
Debug.Assert()
Trace.Assert()
静态构造函数:一个类只能有一个静态构造函数,该构造函数不能有访问修饰符,也不能带任何参数。静态构造函数不能直接调用,只能在下述情况下执行:
? 创建包含静态构造函数的类实例时
? 访问包含静态构造函数的类的静态成员时
无论创建了多少个类实例,其静态构造函数都只调用一次。接口是把公共实例(非静态)方法和属性组合起来,以封装特定功能的一个集合。接口不能单独存在。不能像实例化一个类那样实例化接口。另外,接口不能包含实现其成员的任何代码,而只能定义成员本身。实现过程必须在实现接口的类中完成。接口的名称一般用大写字母I 开头(如IHotDrink)
可删除的对象:支持IDisposable 接口的对象必须实现其Dispose()方法。C#允许使用一种可以优化使用这个方法的结构。using 关键字可以在代码块中初始化使用重要资源的对象,会在这个代码块的末尾自动调用Dispose()方法,用法如下:
或者把初始化时象<VariableName>作为 using语句的一部分:
在这两种情况下,可以在using代码块中使用变量<VariableName>,并在代码块的末尾自动删除(在代码块执行完毕后,调用Dispose())。
定义类时可加的修饰符:
internal:类声明为内部的,即只有当前项目中的代码才能访问它。不加则默认为该值。
public:类是公共的,应该可以由其他项目中的代码来访问。
不可以是protect或private,还有两个可选的互斥的修饰符:
abstract 或 sealed:抽象的(不能实例化,只能继承,可以有抽象成员)或密封的(sealed,不能继承)。
下表是类定义中可以使用的访问修饰符的组合:接口定义跟类基本一样,只是不能在接口中使用关键字 abstract 和 sealed
联合使用 GetType()和typeof(这是一个C#运算符,可以把类名转换为System.Type 对象),就可以进行比较,如下所示:
这段代码将执行下述序列:
执行System.Object.Object 构造函数。
执行MyBaseClass.MyBaseClass(int i)构造函数。
执行MyDerivedClass.MyDerivedClass(int i, int j)构造函数。
执行MyDerivedClass.MyDerivedClass()构造函数。
结构是值类型,而类是引用类型,传递类变量时实际传的是指针,对其一的变量操作也会改变另一变量的值。
readonly,表示这个字段只能在执行构造函数的过程中赋值,或由初始化赋值语句赋值。例如:
访问器,分别用get 和set 关键字来定义,可以用于控制对属性的访问级别。可以忽略其中的一个块来创建只读或只写属性(忽略 get 块创建只写属性,忽略 set 块创建只读属性)。如下定义一个属性:
重写或隐藏的基类方法: 如果继承的成员是虚拟的,就可以用override 关键字重写这段实现代码。无论继承的成员是否为虚拟,都可以用new关键字(非必须,不加会有警告)隐藏这些实现代码。
其中重写方法将替换基类中的实现代码,即使这是通过基类类型进行的,也就将使用新版本:接口成员的定义与类成员的定义相似,但有几个重要的区别:
? 不允许使用访问修饰符(public、private、protected 或internal),所有的接口成员都是公共的。
? 接口成员不能包含代码体。
? 接口不能定义字段成员。
? 接口成员不能用关键字static、virtual、abstract 或sealed 来定义。
? 类型定义成员是禁止的。
但要隐藏继承了基接口的成员,可以用关键字new 来定义它们,例如:
继承一个实现给定接口的基类,就意味着派生类隐式地支持这个接口。如果在基类中把实现代码定义为虚拟,派生类就可以替换该实现代码,而不是隐藏它们。如果要使用new 关键字隐藏一个基类成员,而不是重写它,则方法IMyInterface.DoSomething()就总是引用基类版本,即使通过这个接口来访问派生类,也是这样。
其中 DoSomething()是显式实现的,而 DoSomethingElse()是隐式实现的。只有后者可以直接通过MyClass 的对象实例来访问。
前面说过,如果实现带属性的接口,就必须实现匹配的get/set存取器。这并不是绝对正确的——如果在定义属性的接口中只包含set 块,就可给类中的属性添加get 块,反之亦然。但是,只有所添加的存取器的可访问修饰符比接口中定义的存取器的可访问修饰符更严格时,才能这么做。因为按照定义,接口定义的存取器是公共的,也就是说,只能添加非公共的存取器。例如:部分类定义:如果所创建的类包含一种类型或其他类型的许多成员时,就很容易混淆,代码文件也比较长时可以使用部分类定义,把类的定义放在多个文件中。例如,可以把字段、属
性和构造函数放在一个文件中,而把方法放在另一个文件中。为此,只需在每个包含部分类定义的文件中对类使用partial 关键字即可,如下所示:如果使用部分类定义,partial 关键字就必须出现在包含定义部分的每个文件的与此相同的位置。应用于部分类的接口也会应用于整个类,也就是说,下面的两个定义是等价的:
部分方法定义,部分方法在部分类中定义,但没有方法体,在另一个部分类中包含实现代码。部分方法也可以是静态的,但它们总是私有的,且不能有返回值。它们使用的任何参数都不能是out 参数,但可以是ref 参数。部分方法也不能使用virtual、abstract、override、new、sealed 和extern修饰符。有了这些限制,就不太容易看出部分方法的作用了。实际上,部分方法在编译代码时非常重要,其用法倒并不重要。考虑下面的代码:
在控制台应用程序中调用DoSomething 时,输出如下内容:
如果删除第二个部分类定义,或者删除部分方法的全部执行代码(注释掉代码),输出就如下
所示:
编译代码时,如果代码包含一个没有实现代码的部份方法,编译器会完全删除该方法,还会删除对该方法的所有调用。执行代码时,不会检查实现代码,因为没有检查方法的调用。这会略微提高性能。与部分类一样,在定制自动生成的代码或设计器创建的代码时,部分方法是很有用的。设计器会声明部分方法,用户根据具体情形选择是否实现它。如果不实现它,就不会影响性能,因为该方法在编译过的代码中不存在。所以部分方法不能有返回类型。
封箱(boxing)是把值类型转换为System.Object 类型,或者转换为由值类型实现的接口类型。
拆箱(unboxing)是相反的转换过程。
也可以把值类型封箱到一个接口类型中,只要它们实现这个接口即可:is 运算符并不是说明对象是某种类型的一种方式,而是可以检查对象是否是给定类型,或者是否可以转换为给定类型,如果是,这个运算符就返回 true :<operand> is <type>
如果<type >是一个类类型,而<operand>也是该类型,或者它继承了该类型,或者它可以封箱到该类型中,则结果为true 。
如果<type >是一个接口类型,而<operand>也是该类型,或者它是实现该接口的类型,则结果为 true 。
如果<type >是一个值类型,而<operand>也是该类型,或者它可以拆箱到该类型中,则结果为true 。
as 运算符使用下面的语法,把一种类型转换为指定的引用类型: <operand> as <type>
这只适用于下列情况:
? <operand>的类型是<type >类型
? <operand>可以隐式转换为<type >类型
? <operand>可以封箱到<type >类型中
如果不能从<operand>转换为<type >,则表达式的结果就是null
定义可空类型:泛型使用 System.Nullable<T> 类型提供了使值类型为空的一种方式。例如:
System.Nullable<int> nullableInt;
int? 是System.Nullable<int>的缩写,但更便于读取:
int? nullableInt;
如果 op1 是null ,就会生成System.InvalidOperationException 类型的异常。
??运算符:空接合运算符(null coalescing operator) ,是一个二元运算符,允许给可能等于null
的表达式提供另一个值。如果第一个操作数不是null,该运算符就等于第一个操作数,否则,该运算符就等于第二个操作数。下面的两个表达式的作用是相同的:
对象初始化器(object initializer) ,这是无需在类中添加额外的代码(如此处详细说明的构造函数)就可以实例化和初始化对象的方式:
如:
标签:
原文地址:http://www.cnblogs.com/suoluo/p/5256476.html