创建.NET应用程序的步骤:
1)使用某种.NET兼容语言编写应用程序代码
2)把代码编译为CIL,存储在程序集中
3)执行代码时,使用JIT编译器将代码编译为本机代码
4)在托管的CLR环境下运行本机代码,以及其他应用程序或进程
用字符串表示带路径的文件名,字符串中会带有大量的斜杠,例如:"c:\\Temp\\MyDir\\MyFile.doc",可以在字符串前加一个@符号,这样对于引号,双引号,斜杠等符号就不用在转义了,例如:@"c:\Temp\MyDir\MyFile.doc"
把字符串转换成枚举变量不能使用简单的类型转换,需要用一个特殊的语法:(enumerationType)Enum.Parse(typeof(enumerationType), enumString);
以下方式声明数组:
Type[] name;
这样只是定义了一个数组类型的变量,并没有指定数组的大小,数组中也没有内容,可以在定义的时候初始化,如:
也可以先定义数组,然后再初始化,如:
int[] myIntArray;
myIntArray = new int[5] { 5, 9, 10, 2, 99};
如果定义数组时没有初始化,那么数组中的所有元素都有同一个默认值,对于数值类型来说,其默认值是0,初始化元素的数量必须与数组的长度一致,不能只初始化部分元素,这与C++是不一样的二维数组采用如下方式申明:
int[,] myIntArray;
声明时可不指定任何的维度,因为C#限制初始化列表必须与数组的长度一致,所以根据初始化列表就可以确定数组的长度,但必须采用分段初始化的方式,如:
int[,] myIntArray;
myIntArray = new int[,] { { 1, 2 }, { 2, 3 } };
申明数组的数组,即数组中的每个元素都是一个数组,语法如下:
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[3][]{new int[]{1, 2, 3}, new int[] {1}, new int[] {1, 2}};
C#有一种特殊的函数参数,这种参数只能出现在参数列表的最后一个,叫做参数数组,它有params关键字定义,定义的形式为:
params type[] name
调用方式可以采用
functionname(var1, var2....,varn);
唯一的限制是var等一系列变量必须类型相同并且是type类型的
C#的函数参数默认为值参数,如果需要使用引用参数,需要在函数参数前加上ref关键字,同时在调用函数的地方,也要在参数前加上ref关键字,例如:
int number = 2;
Func(ref number);
static void Func(ref int number)
{
number *= 2;
}
C#可以使用输出参数,需要在函数参数前加上out关键字,同事在调用函数的地方,也要在参数前加上out关键字,例如:
int MaxValue;
Func(ints, out MaxValue);
static void Func(int[] ints, out int MaxValue)
{
MaxValue = ints[0];
foreach (int i in ints)
{
if (i > MaxValue)
{
MaxValue = i;
}
}
}
注意;输出参数可以是未初始化的,即使是经过初始化的,在使用输出参数时,也需要将它看作是未初始化的
函数委托类似与C++中的函数指针,示例如下:
delegate int OperationFunc(int a, int b);
static void Main(string[] args)
{
OperationFunc function = new OperationFunc(Add);
int iResult = 0;
iResult = function(1, 2);
Console.WriteLine(iResult);
function = new OperationFunc(Mulit);
iResult = function(2, 3);
Console.WriteLine(iResult);
Console.ReadKey();
}
static int Add(int a, int b)
{
return a + b;
}
static int Mulit(int a, int b)
{
return a * b;
}
注意,委托定义中是没有static的
Debug.WriteLine()和Trace.WriteLine()都是用于向IDE的输出窗口输出内容,用于程序运行时显示信息,区别在于前者只在debug模式下生效,而后者在debug和release模式下都生效,这些信息也可以在满足某些条件的情况下才输出,分别对应Debug.WriteLineIf()和Trace.WriteLine If()这两个函数,但参数1中的表达式结果为真,则输出要显示的信息
在使用类静态成员变量前,需要对静态成员变量进行初始化,尽管可以在声明时进行初始化,但有时需要比较复杂的初始化,可以使用静态构造函数执行这种初始化任务,一个类只能有一个静态构造函数,该构造函数不能有访问修饰符,也不能带有任何参数,静态构造函数不能直接调用,只能在下述情况下执行:
- 创建包含静态构造函数的类实例时
- 访问包含静态构造函数的类的静态成员时
class MyClass
{
public static int m_i;
static MyClass()
{
Console.WriteLine("静态构造函数被调用");
m_i = 5;
}
}
静态类只能包含静态成员,不需要示例构造函数,静态类可以有一个静态构造函数,示例:
{
static class MyStaticClass
{
static MyStaticClass()
{
}
public static void func()
{
}
public static int m_i;
}
默认情况下,类申明是内部的,即只有当前项目中的代码才能访问它,还可以指定类是公共的,可以由其他项目中的代码来访问,为此,要使用关键字public来进行类声明,还可以指定类是抽象的(abstract,不能实例化,只能继承,可以有抽象成员)或密封的(sealed,不能继承)。
在C#的类定义中,只能有一个基类,如果继承了一个抽象类,就必须实现所继承的所有抽象成员。编译器不允许派生类的可访问性高于基类,也就是说,内部类可以集成于一个公共基类,但公共类不能继承于一个内部类。
申明接口的方式与声明类相似,但使用的关键字是interface,而不是class,访问修饰符关键字public和internal的使用方式是相同的,与类一样,接口也默认定义为内部接口,所以要使接口可以公开访问,必须使用public关键字,不能在接口中使用关键字abstract和sealed,因为这两个修饰符在接口定义中是没有意义的。
无论在派生类上使用什么构造函数,除非明确指定,否则就是用基类的默认构造函数,如需要调用基类的其他构造函数,可以把代码放在方法定义的冒号后面,base关键字用于表示基类,this关键字用于表示当前类,例如:
public Derived() : base(1)
{}
public Derived(int i) : this(1, 2)
{}
public Derived(int i, int j)
{}
相似点
- 抽象类和接口都包含可以由派生类继承的成员
- 接口和抽象类都不能直接实例化,但可以申明这些类型的变量
- 派生类只能集成一个基类,类可以使用任意多个接口
- 抽象类可以拥有抽象成员和非抽象成员,接口成员必须在使用接口的类上实现
- 接口不能包含字段,构造函数、析构函数、静态成员或常量
类与结构很相似,但类是应用类型,而结构是值类型,比如:将一个类对象赋值给另一个类对象,这两个类对象将指向同一块内存,修改一个对象,另一个对象的值也会改变,而将一个结构变量赋值给另一个结构变量,这两个结构变量只是内容一样,指向两块不同的内存