.NET学习心得点滴

一、C#程序是一组类型声明。

(C程序时一组函数和数据类型,C++程序时一组函数和类)

这里的类型是指type,包括:(1)预定义类型:int、bool、string 等;(2)用户定义类型:类类型(class)、结构(struct)、数组(ARRAY)、枚举(enum)、委托(delegate)、接口(interface)、泛型。

类型通过类型声明创建,包含:

(1)要创建的类型的种类;(2)新类型的名称;(3)对类型中每个成员的声明(名称和规格)。array和delegete类型除外,他们不含有命名成员。

一旦声明了类型,就像他们是预定义类型一样。

2、声明类类型的变量所分配的内存是用来保存引用的(保存在栈里),而不是用来保存类对象实际数据的。要为实际数据分配内存,需要使用new运算符。如: myclass mc=new myclass();在这里面,myclass mc是声明,而new myclass()是初始化;同样,int i=2 中,int i 是声明,=2是初始化。

 

二、var关键字。

var关键字只能用在本地变量,即只能用在某个方法、函数内部。(不能用在类里的字段)

只能在变量声明中包含初始化时使用。因为.net可以根据后面的初始化内容推断出var的类型,如果后面没有初始化,是不行的。

一旦推断出类型,就固定不能更改了,它仍然是强类型性质。

.NET的关键字var和JAVASCRIPT中的var是不一样的,js可以引用不同的类型。

 

三、堆栈

栈,是一个内存数组,是后进先出的数据结构。堆:是一块内存区域,在堆里可以分配大块的内存用于存储某种类型的数据。

值类型,数据存放在栈里;引用类型:第一段是一个引用,指向数据在堆里的存放位置,第二段是存储实际的数据,它总是在堆里。

值类型有:

(1)预定义类型:byte/int/long/bool等,仅仅除了:object和string。

(2)自定义类型:struct/enum。除了:class/interface/delegate/array。

所以,对于一个方法,如: void myfun(myclass f1,int f2){f1.hisInt+=1;f2+=1;} ,最终,因为参数是变量的复制,一个是引用,一个是值类型,对于值类型,其内的改变并不影响外面的字段;而引用类型的myclass.hisInt因为是引用类型,所以其外面的堆里的值会被改变。

 

四、属性

属性表面上和类中的“字段”很相似,都是类成员、都有类型、都可以被赋值和读取。

但,属性是一个函数成员,它不为数据存储分配内存!它执行代码。

属性是指定的一组两个匹配、成为访问器的方法(get/set)。

 

只有get访问器的,叫只读属性,只有set访问器的,叫只写属性,但他们至少有一个必须定义。

 

五、委托和事件

(一)、委托是类型,他包含具有相同签名和返回值类型的有序方法列表。当他被调用时,他调用列表中的每一个方法。

如:

delegate void myDel(int x);

myDel delVar1=new myDel(myobj.myM1);

myDel delVar2=myobj.myM2;  //上面和这行的意思一样,只是这行省略了new

myDel delVar3=delVar1 + delVar2;  //或者 delVar1 +=myobj.myM2;

这里,如果执行: delVar1(5),就相当于执行了:myobj.myM1(5);myobj.myM2(5);

(二)、事件不是类型,是成员,所以:

A、由于不是类型,所以不能用new表达式来创建他的对象。

B、由于是成员,所以必须声明在类或结构中,且不能再一段可执行代码中声明对象。

C、事件成员被隐式自动初始化为null。

可以说:事件就是一个封装了的委托,是一个委托类型的变量。

事件声明需要委托类型的名字,如:

class MyTimerClass

{ public event EventHandler myEve; }

其中委托类型的名字可以是自定义的,也可以是.NET BCL预定义的委托类型,建议使用EventHandler,他当时的定义是:

public delegate void EventHandler(object sender,EventArgs e);

其中第一个参数:object sender用来保存触发事件的对象的引用;由于是object,所以可以匹配任何类型的实例。

第二个参数用来保存有关状态对应用程序来说是否合适的状态信息。

但实际上,EventArgs类被设计为不能传递任何参数。他用于不需要传递数据的事件处理程序--通常会被忽略。

如果希望传递数据,必须声明一个从EventArgs类继承的类,使用合适的字段来保存需要传递的数据。譬如:

注:类有9种成员:函数成员:方法、属性、事件、构造函数、Finalizer方法、运算符、索引;数据成员:字段、常量。

其中,能被外界经常看到或引用的是前3种。 所以事件是封装的委托类的变量。

 

 

六、接口 (含枚举和LINQ的一些知识)

1、接口表示一组函数成员而不实现成员的引用类型,包含以下函数成员的声明:方法、属性、事件、索引。BCL中内置了一个IComparable的接口,如下:

public interface IComparable

{ int CompareTo(object obj); }

知道静态方法:Array.Sort(数组)为何可以排序数字、英文、或者汉字吗?因为它会调用这个数组中按IComparable接口要求实现的CompareTo方法,如果是则可以排序,如果不是就没有办法进行排序。

注:接口是引用类型,所以可以通过把类对象引用强制转换为接口类型来获取指向接口的引用,一旦有了接口的引用,就可以使用点号来调用接口的方法。如:Imy imy=(Imy)mc;

2、foreach为何可以列举出其内的所有内容,为何这么神奇?

原因是数组可以按需提供一个叫做枚举数(enumerator)的对象,对于有枚举数的类型而言,必须有一个方法来获取他们。在.NET中获取一个对象枚举数的标准方法就是调用对象的GetEnumerator方法。实现GetEnumerator方法的类型叫做可枚举类型(enumerable)。数组就是可枚举类型。

(1)IEnumerator接口。他包含三个函数成员:Current属性、MoveNext和Reset方法。

(2)IEnumerable接口。仅有一个成员:GetEnumerator方法。

(3)泛型IEnumerable<T>接口。它也包含了一个方法:GetEnumerator方法。然而这个版本的GetEnumeratorfanui实现泛型IEnumerator<T>接口的类对象;由于类必须实现两个GetEnumerator方法,我们需要显示实现非泛型版本,并在类中实现泛型版本。

总之,正因为有了I..or接口的三个成员,所以foreach才可以得以循环列出其内容。

可枚举类型可通过迭代器来进行创建。如:

 

3、LINQ

LINQ查询结果实际是IEnumerable<>,如:

IEnumerable<int> lowNums= from n in numbers select n;

Linq查询可以返回2种类型的结果:枚举(IEnumerable)和标量(scalar),如:

int numsCounts=(from n in numbers select n).Count(); //返回一个整数。

理解查询变量的内容很重要。在执行了以上代码后,lowNums不会包含查询的结果,因为它包含的是IEnumerable<int>类型的对象(也可用var来让计算机识别并代替),是引用类型,放在栈里的是lowNums,他引用的结果是放在堆里面的 IEnumerable<int> 再指向同是堆里面的其他枚举数。所以,查询表达式返回枚举,查询一直到处理枚举时才会被执行。如果枚举被处理多次,查询就会被执行多次。

而,如果查询表达式返回标量,查询会立即执行,并把结果保存在查询变量中,即栈中。

 

4、C#事件与FLEX事件

我认为:C#中的: btn.Click +=btn_click;

等价于FLEX中的:btn.addEventListener(MouseEvent.CLICK,"btn_click");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章