1.C#中main函数必须在一个类中,C#(Java)思想:完全面向对象,从一个对象的生成开始程序。
2.C#中没有作用域运算符::,没有指针运算符->
C#的复合名字一律通过”.”来连接。
3.C#中由引入名字空间代替C,C++中的#include。
4.C#中局部变量声明后必须赋予初值才能使用。
5.C#中各种变量类型实际是一个类,继承至.net基类,拥有各种方法:ToString, Parse 等。
6.C#可以使用指针的功能,但是代码必须用unsafe声明
7.C#中char类型与C++中短整型不同,不允许把数值直接赋予此类型的变量(但可以用单引号加上数值来表示),也不能用char类型参与整形的运算,并且在C#中char采用Unicode字符集,而C,C++采用ANSII字符集;C#中bool值不允许用0,非0表示,只能用true
or false;C#中多了一种decimal(十进制)类型,用于金融和货币方面的计算,使用下标m表示一个浮点数为十进制类型
8.C#中若使用指针等不安全代码以及无符号整型数据类型,此代码不可供.Net下其他语言使用。(CLS中不支持,但是可以编译运行)
9.C#中托管功能可以检查数组越界,防止跨内存的操作。
10.C#中类和结构中每个变量和方法的使用权限必须一一声明(private,public,protected)
C#中只允许单一继承,而不允许多重继承,C#中函数重载等必须以关键字override来显示声明。
11.C#中用get,set表示设置器函数,用于获取或设置类中各权限数据
C#中内置value关键值用于表示set函数中用户传递值
12.C#中object类是所有其他类型的基类,所有类型都直接或间接地从object类中继承
对一个object的变量可以赋予任何类型的值
Object是system.object的别名
13.C#中有四种引用类型: 类,代表,数组,接口
14.C#中delegate(代表),实际上是C#中函数指针的原型,但是此用法是安全的
C#中一般使用引用,与C++中引用类似。
15.C#中数组声明时,方括号放在类型之后表示数组,而不是放在变量名之后。
如int[] array = new int[5] 声明一个有5个int类型元素的数组
C#中各种数组的声明有多种形式
二维数组 int[
, ] array 方括号中间用“ , “隔开 (每维元素个数一致)
三维数组 int[
, , ] 用多个逗号分隔表示多维数组
可变数组 int[][]
用多个中括号表示可变数组,每一维的元素个数可变
Int[][][] …..
16.关于数组的初始化(与C,C++不同的方法)
Int a[] = new int[] {1, 2, 3}
Int a[ , ] = new int[ , ] {{1,2,3},{4, 5, 6}}
Int a[ , ] = new int[10, 20]
Int a[ , , ] = new int[10, 20 ,30]
Int a[][] = new int[3][] 可变数组最高维必须指定
关于可变数组
Int a[][] = new int [3][]
Int a[0] = new int[] {1, 2}
Int a[1] = new int[] {1,2,3}
Int a[2] = new int[] {1,2,3,4}
函数中传递数组示
void function(int[] a); //形式
使用时 int[] array = new int[5]; function(array);或者 function(new int[] {1 ,2 3});
17.C#中 is关键字
如 int i = 5; object obj = (object)i; 此时 object is int 返回 true
注意 任何类型都可以赋值给object类型
因为object类型是所有类型的基类,当赋值发生时,就会有个装箱的过程,object对象中存储了装箱的对象类型和装箱对象的值。
当把一个object类型的对象赋予一个其他类型的变量,对应一个拆箱过程,此时需要注意类型兼容
18.C#中允许用“@”+关键值来命名变量,其中@不是变量的一部分,而是给编译器指出此变量名不是关键字。
19.C#中有7种变量类型
静态变量(static variables),非静态变量(instance variables),数组元素(array
variables),值参数(value variables),引用参数(reference parameters),输出参数(output parameters),局部变量(local variables)
其中引用参数用 ref关键字声明,输出参数用out 关键字声明
20.隐式转换
a.隐式数值转换 向上转型 up-casting 0 可以隐式转换为任意整形
b.隐式枚举转换
c.隐式引用转换
1.任何引用类型到对象类型的转换
2.从类类型s到类类型t的转换,其中s是t的派生类(如int赋值给object)
3.从类类型s到接口类型t的转换,其中t是s的父接口
4.从元素类型为Ts的数组类型S向元素类型为Tt的数组类型T的转换
转换满足条件:
a. S和T只有元素的数据类型不同,但他们的维数相同
b. Ts和Tt都是引用类型(注意:数组元素的类型必须是引用类型)
c. 存在从Ts到Tt的隐式引用转换
d. 从任何数组类型到System.Array的转换
e. 从任何代表类型到System.Delegate的转换
f. 从任何数组类型或代表类型到System.ICloneable(不清楚,待查)的转换
e. 从空类型(null)到任何引用类型的转换
21.通过将数组名作为参数传递给System.WriteLine()可以在控制台打印出数组的系统定义类型.
如 float farray = new float[5];
System.WriteLine(farray);
输出: System.Single[]
类似的 对应
类型
输出结果
double
System.Double[]
sbyte
System.Sbyte[]
byte
System.Byte[]
ushort
System.Int16[]
int
System.Int32[]
long
System.Int64[]
string
System.String[]
22. 显示转换 向下转型(数据截取)
显示转换与C,C++中不同,C#中当显示转换时,编译器(开启checked选项)检查到超出转换后类型的值域而发生的溢出则会抛出异常(OverflowException),其余情况发生数据截取或者精度丢失。Float到double,
decimal大到无法表示或是无穷和NaN则抛出异常InvalidCastException。
显示引用转化包括:
a. 从对象到任何引用类型
b. 从类类型到S到类类型T,其中S是T的基类
c. 从类类型S到接口类型T,其中S不是密封类,而且没有实现T
d. 从接口类型S到类类型T,其中T不是密封类,而且没有实现S
e. 从接口类型S到接口类型T,其中S不是T的子接口
f. 从元素类型Ts的数组类型S到元素类型Tt的数组类型T的转换,而且这种转换满足条件:
i. S和T只有元素类型不同,而维数相同
ii. Ts和Tt都是引用类型
iii. 存在从Ts到Tt的显示引用转换
iv. 从System.Array到数组类型
v. 从System.Delegate到代表类型
vi. 从System.ICloneable到数组类型或者代表类型
为了确保显示引用转换的正常进行,要求源变量的值必须为null或者他所引用的对象的类型可以被隐式引用转换转换为目标类型。否则显示引用转换失败,抛出InvalidCastException异常。
注意:不论是显示引用转换还是隐式引用转换,只改变引用类型,而不改变引用类型指向的数据值的类型。
23.as操作符,通过引用转换或者装箱转换将一个值显示的转换成指定的引用类型。As操作符不会产生任何异常,如果转换不可以进行,则结果值为null
格式 Expresstion(表达式) as Type(引用类型)
24.checked 和 unchecked操作符,用于整形运算时控制当前环境中的溢出检查,如果溢出则抛出OverflowException异常。
注意:checked和unchecked检查异常,只对之后的表达式检查,而不对之后括号中的函数调用内部进行检查.
25. C#中else与离其最近的if对应,
因此 if(a) if(b)e1; else(c) e2;
等价于 if(a){
if(b)
e1;
else?
e2;
}
25.C#中switch语句中各case后如果不加break或者goto语句,不会像C,C++中那样继续执行下一个case,将会报错。
可以用 goto case 值/default进行跳转
在C,C++中switch-case语句只能对整形或者字符型变量有效,对字符串不可使用,而在C#中可以在switch-case语句中使用字符串常量,且case标签中允许null值。
26.C#在流程控制中多了一个foreach关键字
foreach语句表示收集一个集合中的各元素,并针对各个元素执行内嵌语句。
语句格式:
foreach(类型 + 标识符(循环变量) + in(关键字) + 表达式) 嵌套语句
每执行一次内嵌语句,循环变量就依次取集合中的一个元素带入其中。
此处的循环变量是一个只读型局部变量,如果试图改变它的值或将它作为一个ref或者out类型的参数传递,都会引发编译错误。
foreach中表达式是一个集合类型,如果该集合的元素类型与循环变量类型不一致,则必须有一个显示定义的从集合中的元素类型到循环变量元素类型的显示转换。
在C#中集合类型的语法定义:
(1) 该类型必须支持一个形为GetEnumerator()的公有的非静态方法,该方法的返回类型为结构,类或者接口。
(2) 形为GetEnumerator()的方法返回的结构,类或者接口应当包含一个公有的非静态方法MoveNext(),该方法的返回类型为布尔值
(3) 形为GetEnumerator()的方法返回的结构,类或者接口应当包含一个公有的非静态的属性Current(其类型称为集合的元素类型),该属性可以读出。
[数组支持foreach]
27.C#没有独立的预处理器,C# 中的预处理指令仅仅用来和C,C++保持一致,而并不是编译器开始编译代码之前的一个单独的处理步骤,它是作为词法分析的一部分来执行的。
#define #undef应该放在任何非预处理指令之前.
C#中预处理指令如果出现在其他输入输出元素的中间就不会被执行。
如此程序试图在Debug时显示 He is a doctor,否则显示He is a teacher
using System;
class myprog{
static void main(){
Console.WriteLine(@”He is a
#if Debug
doctor
#else
teacher
#endif
“);
}
}
结果输出却为
He is a
#if Debug
doctor
#else
teacher
#else
28.C#与C++异常处理的不同之处
1).在C#中,所有异常都表现为一个类的实例,这个类继承自System.Exception类。而在C++中,任何类型的任何值都可以表示异常。
2).C#中一个终结块里的终结代码既可以在正常情况下执行,也可以在异常情况下执行,而在C++中,不复制代码是难以做到的。
3).在C#中,系统级的异常,如溢出,除数为0等,由于有定义完好的异常类因而可以等同于应用程序及错误条件。
29.异常相关
引发异常的条件:
1).throw语句无条件,即时地抛出异常。
2).C#语句和表达式执行过程中激发了某个异常的条件,使得操作无法正常结束,从而引发异常。
throw语句抛出异常: throw expresstion()
30.C#类定义之后无分号
31.C#中使用internal修饰符修饰的类成员对于同一包中的应用程序或库是透明的,而在包.net之外是禁止访问的。
32.C#中this关键字在类中是引用类型,是类对象自身的引用,而在C++中是指针,指向当前类对象。
32.C#中使用名字空间时using后没有namespace关键字,而在C++中需要使用using
namespace
33.C#中类静态(static)成员不需要在类外进行定义,而在C++中静态在类中进行声明,在类外进行定义,但是不管在这两种语言中任何一种中,静态成员都为所有类对象共同拥有,无论存在多少该类的对象,静态成员在内存中只有一个。
34.C++中允许显示调用析构函数,而在C#中不允许对析构函数进行显示调用。
35.C#中没有全局变量,全局函数,全局常量的概念,在C#中所有的变量,方法必须封装在类中。
36.C#中用ref声明引用参数,使用引用参数时不另开辟内存区域,但是需要初始化。
用out声明输出参数,out修饰符后的参数不需要初始化,作为函数返回值来使用。
37.形参中包含了数组型参数,那么它必须在参数表中位于最后。另外,参数只允许是一维数组。比如,string[]和string[][]类型都可以作为数组参数,而string[
, ]则不能,而且数组型参数不能用ref,
out修饰。
38.C#中readonly修饰符表示此作用域为只读域,readonly标识后只能在类的构造函数和域的定义中进行修改,其他情况下只读。
在C++中使用#define,const定义常量可以在C#中用static+readonly来替代。(注意:const与static+readonly区别在于,const的值在编译时生成,而static+readonly知道程序运行时才形成。)
39.C#中声明后的变量都将有默认初始值,包括自定义的结构。(任何引用的默认初始值为null)域的初始化分为两种形式:对于静态域,类在装载时对其进行初始化;对于非静态域,在类的实例创建时进行初始化。在默认的初始化之前,域的值是不确定的。
40.使用abstract修饰的抽象属性,set,get中只有一个分号“;”。
get访问器用return获取值,set用value设置值。