C#初学笔记
毕业设计要用到c#。
在学过了c++和java后,初看《c#入门经典》和《c#高级编程》,不免在心里把c#和java与c++在语法方面做些比较,做些笔记。
预编译:
像C++一样,c#中有预编译命令
namespace 和 using:
还搞不太懂,和java中import有些相同
基本和数据类型:
像c++中一样有unsigned类型,如uint,ushort等等
goto:
java中被废掉的goto关键字又回来了
const:
定义常量用const关键字;
@:
@符号后面的字符串就是字面的意思(没有转移字符),比如string s = @"\n" 这s就是"\n"而不是一个换行符
foreach:
如int[] intArray = new int[3];foreach(int i in intArray){...}
switch:
可以用于string;default不一定要写在最后一句,但只有在没有case匹配时才会执行;每个case必须有break或return或goto case ...结束,两个或多个case连续写在一起的情况除外
enum:
默认的underlying type是int,从0开始赋值,可以像int一样进行运算,也可以和int相互转换。underlying type也可以是其他的基本数据类型,也可以自己赋值。
01
enum Orientation:byte
02
{
03
east,
04
west=3,
05
north,
06
south=north
07
}
08
...
09
Orientation o = Orientation.south;
10
int i = (byte)o;
11
Orientation east = (Orientation)0;
12
Orientation direction = (Orientation)Enum.Parse(typeof(Orientation), "north");//字符串转化为枚举
typeof:
typeof(Object)感觉像java里面的Object.class;object.GetType()像java里面的object.getClass();
struct:
结构派生于System.ValueType,它又派生于System.Object
结构体struct和class很像,同样可以有属性和方法,也可以实现接口,但struct是值类型,而class是引用类型
1
MyStruct struct1 = new MyStruct();
2
MyStruct struct2 = struct1;
3
//struct1复制了一份给struct2,对struct2的设置不会影响struct1
4
MyClass class1 = new MyClass();
5
MyClass class2 = class1;
6
//对class2的修改会影响class1,因为它们指向同一个实例
ref,out:
ref使得参数按引用传递
1
void Triple(ref int a)
2
{a *= 3;}
3
...
4
int a = 3;
5
Triple(ref a);
6
Console.WriteLine(a);//a变成9
out和ref功能和用法相同,区别在于用ref传入函数的参数必须先初始化,out不用
params:
params关键字使函数可以接受个数任意的参数
int fun(params int[] a)就像java中的int fun(int...a)
Main函数:
有4种static int Main(string[]args),static void Main(string[]args),static int Main(),static void Main()
易做图数组,变长数组:
1
int[][] array = new int[3][];// 变长数组
2
array[0] = new int[3];
3
array[0][1] = 43;
4
5
int[,] array2 = new int[4, 5];//易做图数组
6
array2[0, 1] = 32;
而java中都是变长数组,即数组的数组
checked和unchecked:
使用checked会在溢出是抛出异常,默认是unchecked
1
byte b = 255;
2
checked { b++; }//抛出异常
3
Console.WriteLine(b);
delegate:
委托(代理)好像就是c++中的函数指针,委托也是一种类,派生于System.MulticastDelegate
1
int add(int a,int b){return a+b;}
2
int subtract(int a,int b){return a-b;}
3
delegate int Fun(int a,int b);
4
Fun f = add;
5
int a = f(1,1);//得到2
6
f=subtract;
7
int b = f(1,1);//得到0
多播委托可以使用+、-、+=、-=运算符
集合:
Array和ArrayList等都用中括号[]来索引,Dictionary还可以用任意类型的引索(这让我想到了js)
1
Dictionary<string, int> dic = new Dictionary<string, int>();
2
List<int> l = new List<int>();
3
...
4
int a = (int)al[0];
5
int b = dic["haha"];
函数重载:
virtual显式指定虚函数或虚属性。不用virtual则默认不是虚拟的(这和C++一样,而java则默认都是虚拟的)。
override关键字用于重载虚函数,new关键字用于显式声明子类的函数隐藏了父类的同名函数。
01
class A
02
{
03
public void M() { Console.WriteLine("a"); }
04
public virtual void V() { Console.WriteLine("a"); }
05
}
06
class B : A
07
{
08
public new void M() { Console.WriteLine("b"); }
09
public override void V() { Console.WriteLine("b"); }
10
}
11
...
12
A a = new B();
13
B b = new B();
14
a.M();//a
15
a.V();//b
16
b.M();//b
17
b.V();//b
虚函数的调用取决于实例的类型,而非虚函数的调用取决于引用变量的类型
试了一下发现verride不能和virtual一起用,但如果将来有一个C类要重载B类的V()方法,怎么使B.V()成为虚函数啊?
操作符重载:
重载的方法和C++中的一样(记得学C++时我最喜欢这个了,很方便啊),但限制比C++多。比如必须声明为public和static;不能重载“+=”,重载“+”之后“+=”自然可以使用;不能重载“=”;可以重载“&”,不能重载“&&”;“<”和“>”、“<=”和“>=”、“!=”和“=”要成对重载,不能只重载一个;而且好像只能重载成静态static的。
1
class Time
2
{
3
public int hour, min;
4
public Time(int h, int m) { hour = h; min = m; }
5
public static Time operator +(Time a, Time b)
6
{ return new Time(a.hour + b.hour, a.min + b.min); }
7
}
自定义数据类型转换:
很强大啊,用法像重载操作符一样,同样必须是public static。可以在类和基本数据类型之间,类和类之间转换。implicit说明可以隐式转换,explicit指明必须显示转换。转换函数必须写在源类型或目标类型的类或结构体定义里面,有继承关系的本来就可以转换的类之间不能重载。
01
class C
02
{
03
public int x;
04
public C(int i) { x = i; }
05
public static implicit operator int(C c) { return c.x; }
06
public static explicit operator C(int i) { return new C(i); }
07
}
08
...
09
int i = new C(3);//i=3
10
C c = (C)5;//c.x=5
11
byte b = (byte)new C(2);//b=2,C被转换成int类型后被转换成byte
boxing和unboxing:
在引用类型和值类型之间相互装换,boxing是自动进行的,而unboxing是要显式说明的
1
int i = 0;
2
object o = i;//i被自动装箱成引用类型o
3
string str = 2.ToString();//2被被自动装箱成一个临时的引用类型
4
int b = (int)o;//取消装箱
5
Console.WriteLine(Object.ReferenceEquals(i,i));
6
//值类型用ReferenceEquals(a,b)函数进行比较总是得到false,因为装箱之后的引用变量指向了原来值类型变量的一份拷贝,而不是原值。这样对装箱对象的操作不会影响原来的值类型的内容。
《C#高级编程》上的意思是:定义结构体时,.Net Framework会隐式的提供一个隐式类,与结构体相同,却是一个引用类型,用于装箱。枚举类型也有类似情况。
is和as:
“is”和java中的“instanceof”相当;as用于尝试类型转换
1
ClassA a = (ClassB)b;//无法转换时可能抛出异常
2
ClassA a = b as ClassA//无法转换时a=null
事件:
事件处理时c#使用委托,感觉概念上和OOP思想不太相符,不如java中易做图的概念清晰。
关于类的可见性:
protected——只能由类或派生类的访问
internal——只能由定义它的
补充:软件开发 , C# ,