C#心得体会(5篇模版)

时间:2019-05-12 06:12:30下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《C#心得体会》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《C#心得体会》。

第一篇:C#心得体会

C#心得体会10计算机应用1班全博鹏

刚学习C#的时候,感觉很难,做的时候出现很多错误而且我是照着书打代码还有错误,那时的感觉是迷茫的。在学习的过程中,我还是坚持下来,虽然学的不是很好,但是慢慢就理解了,现在也不要仿照书打代码。现在讲讲做项目的感想。我们项目做不好也有一个小原因,是因为我们三个项目同时进行,而三个项目不同,在需求分析方面没有弄好,导致后面在做项目时,数据库出现了很多问题,所以我觉得现在我们项目不要做多,而是好好做一个项目,从需求开始就要做好每一步,到后面编程才不会出现特别多的错误。

不得不说:“在老师检查完第一次之后,我去看了一下师兄做过的项目,就觉得自己这个项目相差太远了。我觉得我有以下几方面做不好:1.在刚上C#时老师叫我们现在就要做项目但我没有,一直等到老师快要检查时才急急忙忙的做。2.老师上完课,自己做完作业之后,没有好好的复习。其实我觉得三层架构也不难,三层结构就是主要调用了类,而类中定义了方法,归根到底我们还是引用了类中的方法实现它的功能,类就类似于C语言里的函数,因为在数据访问层要用到数据操作类所以要创建一个数据操作类。而我们建三层架构是为了就是倒觉得在表示层里实现一些功能能时要去分析,但是C#语言只学习过浅的知识,数据结构我们也没有学习所以分析起来就有点问题。但是所有问题都是觉得自己太懒,如果自己好好自学数据结构,学习离散数学,也许在分析功能模块会得到提高。所以本人决定寒假做一个像样的项目出来。无论是学习还是做项目的过程中,耐心都要非常重要。有时出现错误,上网查了,自己又想了很久,又找同学讨论还是不能解决时就会有不想做的念头。因为自己曾经在大一时就是因为连关机都不会关,当时都吓到宿舍友了,觉得还是转专业好了。虽然转专业没有成功,但是自从开始学习C语言之后,就慢慢的喜欢计算机应用技术这个专业了,觉得它很有趣,当在做项目成功的实现它功能时,心理就特别高兴,就好想再做几个功能。但是事实不是一下就能成功的实现它的功能所以耐心非常重要。

最重要的一点是我们做项目时,我们要有团队的合作精神。只有这样我们才能很好的完成一个好的项目,才能完成一个项目。就好比如在三层架构中,小组成员要知道我在数据访问层和业务逻辑层用了什么方法,这个方法的作用是什么作用,再表示层里才更好的实现功能。我最大的愿望就是几个想学习的同学在一起讨论问题,只有这样才能进步更快,才能学到更多的知识。

最后想说:“一分耕耘,一分收获。“项目不是做的很好,但是通过项目学到了更多的知识。

全博鹏

第二篇:C#学习心得

集合声明:类B可以换成任意object对象

1、CollectionBase

类A继承CollectionBase类,通过CollectionBase的成员List实现类A的Add(类

B)、Remove(类B)和RemoveAt(类B)方法:

publicvoidAdd(类B newB)

{List.Add(newB);}

publicvoidRemove(类B newB)

{List.Remove(newB);}

publicvoidRemoveAt(int index)

{List.RemoveAt(index);}

在类A中建立索引可以按类似数组的方法访问。

public 类B this[int index]

{get{return(类B)List[index];}

set{List[index]=value;}

}

利用CollectionBase的成员InnerList(ArrayList对象)实现类A的Contains()方法:

publicboolContains(类B newB)

{

returnInnerList.Contains(newB);

}

注意:InnerList是ArrayList类实例,其Contains方法通过调用Object.Equals确定相等性,Equals默认实现仅支持引用相等。对于引用类型,相等定义为对象相等,即这些引用是否引用同一对象。对于值类型,相等定义为按位相等。

可以在类B中重写Object.Equals方法和GetHashCode()方法。publicoverrideboolEquals(objectobj)

{//Check for null and compare run-time types.if(obj == null || GetType()!= obj.GetType())returnfalse;

B b =(B)obj;

return(比较逻辑);

}

publicoverrideintGetHashCode(){„„}

2、DictionaryBase

类A继承DictionaryBase类,通过DictionaryBase的成员

Dictionary(IDictionary类型的接口),实现类A的 Add(object key,类B)和Remove(object key,类B)方法:

publicvoidAdd(object key,类B newB)

{Dictionary.Add(key,newB);}

publicvoidRemove(object key,类B newB)

{Dictionary.Remove(key,newB);}

在类A中建立索引可以按类似数组的方法访问。

public 类B this[object index]

{get{return(类B)Dictionary[index];}

set{Dictionary[index]=value;}

}

利用DictionaryBase的接口成员Dictionary实现类A的Contains()方法: publicboolContains(object key)

{

returnDictionary.Contains(key);

}

3、迭代器

对于继承CollectionBase类的A,使用

foreach(BsourceBin类A对象){}

对于继承DictionaryBase类的A,使用

foreach(DictionaryEntrysourceBin类A对象){source.Value.}

对于类迭代,使用方法GetEnumerator(),返回类型是IEnumerator;类成员迭代使用IEnumerable(),返回类型是IEnumerable;

例如继承DictionaryBase类的A的迭代器,public new IEnumeratorGetEnumerator()

{foreach(object b in Dictionary.Values)

yield return(B)b;

}

以后使用foreach循环时,可按照类似继承CollectionBase类的的方式使用。

4、浅度复制与深度复制

浅度复制:简单地按照成员复制对象可以通过派生于System.Object的MemberwiseClone()方法来完成,这是一个受保护的方法,但是很容易在对象上定义一个调用该方法的公共方法例如GetCopy()。这个方法的复制功能成为浅复制。浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝,但是string类例外,因为string是readonly的,当改变string类型的数据值时,将重新分配了内存地址。数组、类也是浅度复制,而结构体、数值型、枚举是深度复制。

深度复制:需要深度复制的类A添加ICloneable接口,实现该接口的Clone()方法。

public object Clone()

{A newA=new A();

object []arr=new object[维度];//object 可以是数值类型,string //不能使用newA.arr=arr;因为通过数组名赋值引用同一地址,是浅度复制 arr.CopyTo(newA.arr,0);

returnnewA;}

假设类A中有成员对象类B实例myB,则在类B定义中也要实现ICloneable的Clone()方法,class B:ICloneable

{

public object Clone(){„„}

}

然后在类A的Clone方法中,newA.myB=myB.Clone();

比较

1、is运算符

检查对象是否是给定类型或者是否可以转换为给定类型,是则返回true。 is

如果type是类类型,operand也是该类型,或继承该类型、封箱到该类型,为true 如果type是接口类型,operand也是该类型,或实现该接口的类型,为true 如果type是值类型,operand也是该类型,或拆箱到该类型,为true2、运算符重载

public static 返回类型 operator 需重载的运算符(参数„„){}

注意不能重载赋值运算符,&&和||运算符,但可重载&和|;有些运算符需成对重载,如“<”和“>”

3、IComparable接口

类A实现IComparable接口的方法intCompareTo(objectobj)后,利用成员为类A的实例的ArrayList或Array类可以调用Sort()方法,按CompareTo(objectobj)的方法排序。

4、IComparer接口

类A实现IComparer接口的方法intCompare(objectx, objecty)后,利用ArrayList或Array类可以调用Sort(IA)方法(IComparer IA=new A()),按

Compare(,)方法排序。注意ArrayList或Array类的实例不一定是类A。也可以在类A中定义一个公用动态接口成员IComparer ID,这样可以直接调用Sort(ID)。另外,在Compare方法中可以调用Comparer.Default.Compare(,)方法,实现特定的关键字排序。Default是Compare类的动态实例。

转换

1、隐式和显示转换

在没有继承关系,没有共享接口的类型之间转换时,必须定义类型之间的隐式和显示转换。public classA

{„„

//定义A到B的隐式转换

public staticimplicit operatorzhuanB(Aa){„„ return }

}

public classB

{„„

//定义B到A的显式转换

public staticexplicit operatorzhuanA(Bb){„„return }

}

2、as运算符

把类型转换为给定类型。

is

operand类型是type类型,或可以隐式转换为type类型,或封箱到type类型 如果不能转换,则表达式的结果是null

异常处理

Exception:所有异常对象的基类。

SystemException:运行时产生的所有错误的基类。

IndexOutOfRangeException:当一个数组的下标超出范围时运行时引发。NullReferenceException:当一个空对象被引用时运行时引发。

InvalidOperationException:当对方法的调用对对象的当前状态无效时,由某些方法引发。

ArgumentException:所有参数异常的基类。

ArgumentNullException:在参数为空(不允许)的情况下,由方法引发。ArgumentOutOfRangeException:当参数不在一个给定范围之内时,由方法引发。

InteropException:目标在或发生在CLR外面环境中的异常的基类。ComException:包含COM类的HRESULT信息的异常。

SEHException:封装Win32结构异常处理信息的异常。

SqlException:封装了SQL操作异常。

常见具体的异常对象:

ArgumentNullException一个空参数传递给方法,该方法不能接受该参数ArgumentOutOfRangeException参数值超出范围

ArithmeticException出现算术上溢或者下溢

ArrayTypeMismatchException试图在数组中存储错误类型的对象

BadImageFormatException图形的格式错误

DivideByZeroException除零异常

DllNotFoundException找不到引用的DLL

FormatException参数格式错误

IndexOutOfRangeException数组索引超出范围

InvalidCastException使用无效的类

InvalidOperationException方法的调用时间错误

NotSupportedException调用的方法在类中没有实现

NullReferenceException试图使用一个未分配的引用OutOfMemoryException内存空间不够

StackOverflowException堆栈溢出

第三篇:C#总结

引用类型是类型安全的指针,它们的内存是分配在堆(保存指针地址)上的。String、数组、类、接口和委托都是引用类型。

强制类型转换与as类型转换的区别:当类型转换非法时,强制类型转换将抛出一System.InvalidCastException异常,而as不会抛出异常,它返回一个null值。用using创建别名:using console = System.Console;访问限定符:

public 该成员可以被其他任何类访问 protected 该成员只能被其派生类访问

private 该成员只能被本类的其他成员访问 internal 该成员只能在当前编译单元的其他成员访问 带参数列表和返回值的Main方法: class Test {

public static int Main(string[] args)

{

foreach(string arg in args)

{

...}

} } 构造函数(constructor)包括实例构造函数和静态构造函数。构造函数与类名相同,且不能有返回值。例:

class TestClass {

TestClass()//实例构造函数:可以访问静态成员和实例成员,用于初始化实例成员

{

...}

static TestClass()//静态构造函数:只能访问静态成员,用于初始化静态成员

{

...} } 类的静态成员属于类所有,不必生成实例就可以访问,它是在载入包含类的应用程序时创建的,但静态方法不能访问类的实例变量和方法。通常,静态变量是在定义时就赋初始值的。类的实例成员属于类的实例所有,不创建实例对象就无法对其进行访问,实例成员可以访问类的

静态成员和其它实例成员。调用基类的析构函数: class A {

public A()

{

...} } class B {

public B(): base()//调用基类的析构函数

{

...} } 常量:其值是在编译时设定的,必须是数值文字。默认状态下常量是静态的。例: class A {

public const double pi = 3.1415;} 常量是编译时就确定的值,只读字段是在运行才能确定的值。比如运行时才能确定的屏幕分辨率。

只读字段只能在类的析构函数中赋值。静态只读字段: class A {

public static readonly int ScreenWidth;//静态只读字段

static A()

//静态析构函数

{

ScreenWidth = 1024;//在静态析构函数中初始化

} } 在类的继承中,类的析构函数是不会被继承的。一个派生类只能从一个基类继承,不能同时从多个基类继承,但可以通过继承多个接口来达到相同目的。实现多继承的唯一方法就是使用接口。例:

class MyFancyGrid: Control, ISerializable, IDataBound {...} 密封类是不能继承的类,抽象类不能被定义为密封类,且密封类的私有成员不能用protected修饰,只能用private。例: sealed class A {...} 关键字ref和out用于指定用引用方式传递方法的参数。

它们的区别是:ref参数必须初始化,而out参数不需要初始化。所以在方法处理代码依赖参数的初始化值时使用ref,不依赖初始化值时使用out。对out参数即使在传递前对其进行了初始化,其值也不会传递到方法处理函数内部。传递时系统会将其设为未初始化。所以在方法内部必须对out参数进行初始化。

方法重载时,必须参数数目和参数类型其中之一不同,返回值不同不能作为重载。C#不支持方法的默认值,只能通过方法重载来实现。例: class A {

int Method(int a)

{

...}

void Method(int a, int b)//参数数目不同

{

//返回值不同不能作为重载

...} } params参数用于一个不定数目参数的方法,一般后面跟一个数组。例: class A {

public void Method(params int[] i)

{

...} } 方法的覆盖:指派生类覆盖基类的同名方法,有二种方法

1)第一种是在派生类要覆盖的方法前面加new修饰,而基类不需要作任何改动。这种方法的缺点是不能实现多态。例: class A {

public void Method()//无需任何修饰

{

...} } class B: A

//从基类继承

{

new public void Method()//覆盖基类的同名方法

{

...} } class TestClass {

A Instance = new B();

Instance.Method();//这时将调用类A的Method方法,而不是类B的Method方法 } 2)第二种是在派生类要覆盖的方法前面加override修饰,而基类的同名方法前面加virtual修饰。这样就能实现多态,例: class A {

virtual public void Method()

//基类定义虚方法

{

//虚拟方法不能定义为private,因为private成员对派生类是无法访问的...} }

class B: A

//从基类继承 {

override public void Method()

//派生类覆盖基类的同名虚方法

{

...} } class TestClass {

protected void Test()

{

A Instance = new B();

//定义一个实例,类型为基类,从派生类创建

//派生类总是能够向上转换为其基类

Instance.Method();

//将调用派生类B的Method方法,而不是基类的,这就是多态

} } 说明:new修饰的方法覆盖不能实现多态的原因,是因为使用new时编译器只会实现早期绑定(early binding)。即调用的方法在编译时就决定了:编译器看到Instance.Method()而Instance的类是A,就会调用类A的Method()方法。

override修饰的方法覆盖可以实现多态的原因,是因为实现了后期绑定(late binding)。使用override时强制编译器在运行时根据类的真正类型正确调用相应的方法,而不是在编译时。

而基类的同名方法必须加virtual修饰。

类的静态方法可能通过 类名.静态方法名 这种格式来调用,不能使用 实例名.静态方法名 这种方法调用。

因为类的静态方法为类所有(是属于类本身的),而非实例所有(不是属于类的实例的)。类的静态方法可以访问类的任何静态成员,但不能访问类的实例成员。C#中类的变量称为字段。类的public变量称为类的公共字段。

类的属性由一个protected(也可以是private)字段和getter和setter方法构成: class Address {

protected string zipCode;//protected字段,注意大小写

public string ZipCode

{

get

//getter方法

{

return zipCode;

}

set

//setter方法

{

zipCode = value;//被传递的值自动被在这个value变量中

}

};} 只读属性是指省略setter方法的属性,只读属性只能读取,不能设置。

属性也可以用限定符virtual,override和abstract修饰,功能同其他类的方法。

属性有一个用处称为懒惰的初始化(lazy initialization)。即在需要类成员时才对它们进行初始化。如果类中包含了很少被引用的成员,而这些成员的初始化又会花费大量的时候和系统资源的话,懒惰的初始化就很有用了。C#中数组对象共同的基类是System.Array。将数组声明为类的一个成员时,声明数组与实例化数组必须分开,这是因为只能在运行时创建了类的实例对象之后,才能实例化数组元素值。声明:

int[] intArray;//一维数组 int[,] int3Array;//三维数组 初始化:

intArray = new int[3] {1,2,3};int[,] int2Array = new int[2,3] {{1,2,3},{4,5,6}};//声明时可以初始化 遍历:

1)一维数组

for(int i = 0;i < intArray.Length;i++);//Array.Length返回数组所有元素的个数 foreach(int i in intArray);for(int i = 0;i < intArray.GetLength(0);i++);//Array.GetLength(0)返回数组第一维的个数 2)多维数组

for(int i = 0;i < int3Array.GetLength(0);i++)//遍历三维数组

for(int j = 0;j < int3Array.GetLength(1);j++)

for(int k = 0;k < int3Array.GetLength(2);k++)

{

...} 数组的维数就是该数组的秩(Rank)。Array.Rank可以返回数据的秩。锯齿数组(jagged Array)是元素为数组的数组,例:

int[][] jaggedArray = new int[2][];//包含二个元素,每个元素是个数组 jaggedArray[0] = new int[2];//每个元素必须初始化 jaggedArray[1] = new int[3];for(int i = 0;i < jaggedArray.Length;i++)//遍历锯齿数组

for(int j = 0;j < jaggedArray[i].Length;j++)

{

...} 类的属性称为智能字段,类的索引器称为智能数组。由于类本身作数组使用,所以用this作索引器的名称,索引器有索引参数值。例: using System;using System.Collections;class MyListBox {

protected ArrayList data = new ArrayList();

public object this[int idx] //this作索引器名称,idx是索引参数

{

get

{

if(idx >-1 && idx < data.Count)

{

return data[idx];

}

else

{

return null;

}

}

set

{

if(idx >-1 && idx < data.Count)

{

data[idx] = value;

}

else if(idx = data.Count)

{

data.Add(value);

}

else

{

//抛出一个异常

}

}

} } 接口是二段不同代码之间约定,通过约定实现彼此之间的相互访问。C#并不支持多继承,但通过接口可实现相同功能。当在接口中指定了实现这个接口的类时,我们就称这个类“实现了该接口”或“从接口继承”。一个接口基本上就是一个抽象类,这个抽象类中除了声明C#类的其他成员类型——例如属性、事件和索引器之外,只声明了纯虚拟方法。接口中可以包含方法、属性、索引器和事件——其中任何一种都不是在接口自身中来实现的。例:

interface IExampleInterface {

//property declaration

int testProperty { get;}

//event declaration

event testEvevnt Changed;

//mothed declaration

function void testMothed();

//indexer declaration

string this[int index] { get;set;} } 说明:定义接口时,在方法、属性、事件和索引器所有这些接口成员都不能用public之类的访问限定符,因为所有接口成员都是public类型的。因为接口定义了一个约定,任何实现一个接口的类都必须定义那个接口中每一个成员,否则将编译失败。例: using System;public class FancyControl {

protected string data;

public string Data

{

get {return this.data;}

set {data = value;}

} } interface IValidate {

bool Validate();//接口方法

} public class MyControl: FancyControl, IValidate {

public MyControl()

{

data = “my control data”;

}

public bool Validate()//实现接口

{

if(data == “my control data”)

return true;

else

return false;

} } class InterfaceApp {

MyControl myControl = new MyControl();

IValidate val =(IValidate)myControl;//可以将一个实现某接口的类,转换成该接口

bool success = val.Validate();//然后可调用该接口的方法 } 也可以用:bool success = myControl.Validate();这种方法来调用Validate方法,因为Validate在类MyControl中是被定义成public的,如果去除public,Validate方法被隐藏,就不能用这种方法调用了,这样隐藏接口方法称为名字隐藏(name hiding)。可以用:类实例 is 接口名 来判断某个类是否实现了某接口,例: myControl is IValidate //MyControl类的实例myControl是否实现了IValidate接口

当然,也可用as来作转换,根据转换结果是否为null来判断某个类是否实现了某接口,例: IValidate val = myControl as IValidate;if(null == val){...//没有实现IValidate接口 } else {...//实现了IValidate接口

}

如果一个类从多个接口继承,而这些接口中如果定义的同名的方法,则实现接口的方法时,必须加接口名来区别,写成 接口名.方法名。假设Test类从IDataStore和ISerializable二个接口继承,而这二个接口都有SaveData()方法,实现SaveData()方法时必须写成: class Test: ISerializable, IDataStore {

void ISerializable.SaveData()

{

...}

void IDataStore.SaveData()

{

...} } 如果一个类从多个接口继承,为了方便可以定义一个新的接口,这个接口继续多个接口,然后类直接从这个接口继承就可以了,这个叫合并接口。例: interface ISaveData: ISerializable, IDataStore { //不需要定义任何方法或成员,只是用作合并 } class Test: ISaveData //只要继承ISaveData就可以了 {...} C# 操作符优先级(从高到低)

初级操作符()x.y f(x)a[x] x++ x--new typeof sizeof checked unchecked 一元操作符 +位移操作符 << >> 关系操作符 < > <= >= is 等于操作符 == 逻辑与

& 逻辑异或 ^ 逻辑或

| 条件与

&& 条件或

|| 条件操作符 ?: 赋值操作符 = *= /= %= +=-= <<= >>= &= ^= |= 所有的二元操作符除赋值符外都是左联合的,即从左到右计算。

typeof()运算符可以从一个类名得到一个System.Type对象,而从System.Object对象继承来的GetType()方法则可从一个类实例来得到一个System.Type对象。例: Type t1 = typeof(Apple);//Apple是一个类名

Apple apple = new Apple();//apple是Apple类的一个实例 Type t2 = apple.GetType();//t1与t2是相同的 通过反射得到一个类的所有成员和方法: Type t = typeof(Apple);string className = t.ToString();//得到类名

MethodInfo[] methods = t.GetMethods();//得到所有方法 foreach(MethodInfo method in methods){ //用method.ToString()得到方法名 } MemberInfo[] members = t.GetMembers();//得到所有成员 foreach(MemberInfo member in members){ //用member.ToString()得到成员名 } sizeof()操作符用来计算值类型变量在内存中占用的字节数(Bytes),并且它只能在unsafe(非安全)

代码中使用。例:

static unsafe public void ShowSizes(){

int i, j;

j = sizeof(short);

j = sizeof(i);} 尽可能使用复合赋值操作符,它比不用复合赋值操作符的效率高。for语句的语法为:

for(initialization;Boolean-expression;step)

embedded-statement 在initialization和step部份还可以使用逗号操作符,例: for(int i = '0', j = 1;i <= 'xFF';i++, j++)for(int i = 1, j = 1;i < 1000;i += j, j = i!~ ++--true false 二元:+32)/ 9)* 5;

} } 代表的(delegate)目的与C++中的函数指针相同,代表不是在编译时被定义的,而是在运行时被定义的。

代表主要有二个用途:回调(Callback)和事件处理(event)回调通常用于异步处理和自定义处理。例: class DBManager {

static DBConnection[] activeConnections;

//声明回调函数

public void delegate EnumConnectionCallback(DBConnection connection);

public static void EnumConnections(EnumConnectionCallback callback)

{

foreach(DBConnection connection in activeConnections)

{

callback(connection);//执行回调函数

}

} } //调用

class DelegateApp {

public static void ActiveConncetionCallback(DBConnection connection)//处理函数

{

...}

public void main()

{

//创建指向具体处理函数的代表实例(新建一个代表,让它指向具体的处理函数)

DBManager.EmnuConnectionCallback myCallback = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

DBManager.EnumConnections(myCallback);

} } //使用静态代表,上面的调用改为 class DelegateApp {

//创建一个指向处理函数的静态代表

public static DBManager.EmnuConnectionCallback myCallback

= new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

public static void ActiveConncetionCallback(DBConnection connection)

{...} public void main()

{

DBManager.EnumConnections(myCallback);

} } //在需要时才创建代表,上面的调用改为

class DelegateApp {

//将创建代表放在属性的getter方法中

public static DBManager.EmnuConnectionCallback myCallback

{

get

{

retun new DBManager.EmnuConnectionCallback(ActiveConncetionCallback);

}

}

public static void ActiveConncetionCallback(DBConnection connection)

{...} public void main()

{

DelegateApp app = new DelegateApp();//创建应用程序

DBManager.EnumConnections(myCallback);

} } 可以将多个代表整合成单个代表,例: class CompositeDelegateApp {

public static void LogEvent(Part part)

{

...}

public static void EmailPurchasingMgr(Part part)

{

...}

public static void Main()

{

//定义二个代表

InventoryManager.OutOfStockExceptionMethod LogEventCallback

= new InventoryManager.OutOfStockExceptionMethod(LogEvent);

InventoryManager.OutOfStockExceptionMethod EmailPurchasingMgrCallback

= new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);

//整合为一个代表,注意后加的代表先执行(这里是先执行LogEventCallback)

InventoryManager.OutOfStockExceptionMethod onHandExceptionEventsCallback

= EmailPurchasingMgrCallback + LogEventCallback;

//调用代表

InventoryManager mgr = new InventoryManager();

mgr.ProcessInventory(onHandExceptionEventsCallback);

//InventoryManager类的ProcessInventory方法的原型为:

//public void ProcessInventory(OutOfStockExceptionMethod exception);

} } 可以根据需要将多个代表自由地组合成单个代表,例: class CompositeDelegateApp {

//代表指向的处理函数(三个代表三个函数)

public static void LogEvent(Part part)

{

...} public static void EmailPurchasingMgr(Part part){...}

public static void EmailStoreMgr(Part part)

{

...}

public static void Main()

{

//通过数组定义三个代表

InventoryManager.OutOfStockExceptionMethod[] exceptionMethods

= new InventoryManager.OutOfStockExceptionMethod[3];

exceptionMethods[0] = new InventoryManager.OutOfStockExceptionMethod(LogEvent);

exceptionMethods[1] = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr);

exceptionMethods[2] = new InventoryManager.OutOfStockExceptionMethod(EmailStoreMgr);

int location = 1;

//再定义一个代表(用于组合成单代表)

InventoryManager.OutOfStockExceptionMethod compositeDelegate;

//根据需要组合

if(location = 2)

{

compositeDelegate = exceptionMethods[0] + exceptionMethods[1];

}

else

{

compositeDelegate = exceptionMethods[0] + exceptionMethods[2];

}

//调用代表

InventoryManager mgr = new InventoryManager();

mgr.ProcessInventory(compositeDelegate);

} } C#的事件遵循“发布——预订”的设计模式。在这种模式中,一个类公布能够出现的所有事件,然后任何的类都可以预订这些事件。一旦事件产生,运行环境就负责通知每个订户事件已经发生了。

当代表作为事件的处理结果时(或者说定义具有代表的事件),定义的代表必须指向二个参数的方法:一个参数是引发事件的对象(发布者),另一个是事件信息对象(这个对象必须从EventArgs类中派生)。例: using System;

class InventoryChangeEventArgs: EventArgs //事件信息对象,从EventArgs类派生 {...//假设定义二个public属性string Sku和int Change } class InventoryManager

//事件的发布者 {

//声明代表

public delegate void InventoryChangeEventHander(object source, InventoryChangeEventArgs e);

//发布事件,event关键字可将一个代表指向多个处理函数

public event InventoryChangeEventHandler onInventoryChangeHander;

public void UpdateInventory(string sku, int change)

{

if(change == 0)

return;

InventoryChangeEventArgs e = new InventoryChangeEventArgs(sku, change);

//触发事件

if(onInventoryChangeHandler!= null)//如果有预订者就触发

onInventoryChangeHandler(this, e);//执行代表指向的处理函数

} } class InventoryWatcher

//事件的预订者 {

public InventoryWatcher(InventoryManager mgr)//mgr参数用于联结发布者

{

this.inventoryManager = mgr;

//预订事件,用 += 调用多个处理函数

mgr.onInventroyChangeHandler += new InventoryManager.InventoryChangeEventHandler(onInventoryChange);

//事件处理函数

void onInventroyChange(object source, InventroyChangeEventArgs e)

{

...}

InventoryManager inventoryManager;

} } class EventsApp

//主程序 {

public static void Main()

{

InventoryManager inventoryManager = new InventoryManager();

InventoryWatcher inventoryWatcher = new InventoryWatcher(inventoryManager);

inventoryManager.UpdateInventory(“111 006 116”,-2);

inventoryManager.UpdateInventory(“111 006 116”, 5);

} } Microsoft Windows NT和IBM OS/2等操作系统都支持占先型多任务。在占先型多任务执行中,处理器负责

给每个线程分配一定量的运行时间——一个时间片(timeslice)。处理器接着在不同的线程之间进行切换,执行相应的处理。在单处理器的计算机上,并不能真正实现多个线程的同时运行,除非运行在多个处理器 的计算机上。操作系统调度的多线程只是根据分配给每个线程时间片进行切换执行,感觉上就像同时执行。

上下文切换(context switching)是线程运行的一部分,处理器使用一个硬件时间来判断一个指定线程的时间片何时结束。当这个硬件计时器给出中断信号时,处理器把当前运行的线程所用的所有寄存器(registers)数据存储到堆栈中。然后,处理器把堆栈里那些相同的寄存器信息存放到一种被称为“上下文结构”的数据结构中。当处理器要切换回原来执行的线程时,它反向执行这个过程,利用与该线程相关的上下文结构,在寄存器里重新恢复与这一线程相关的信息。这样的一个完整过程称为“上下文切换”。多线程允许应用程序把任务分割为多个线程,它们彼此之间可以独立地工作,最大限度地利用了处理器时间。using System;using System.Threading;class SimpleThreadApp {

public static void WorkerThreadMethod()//线程的执行体

{

...//执行一些操作

}

public static void Main()

{

//创建一个线程代表指向线程的执行体,ThreadStart是创建新线程必须用到的代表

ThreadStart worker = new ThreadStart(WorkerThreadMethod);

Thread t = new Thread(worker);//用线程代表创建线程

t.Start();

//执行线程

} } 可以通过两种方式来得到一个Thread对象:一种是通过创建一个新线程来得到,如上例;另一种在正在执行的线程调用静态的Thread.CurrentThread方法。

静态方法Thread.Sleep(int ms)可以让当前线程(它自动调用Thread.CurrentThread)暂停指定毫秒的时间。

如果使用Thread.Sleep(0)那么当前线程将一直处于等待中,直到另一个线程调用这个线程的实例方法Thread.Interrupt方法,等待才会结束。使用Thread.Suspend方法也能挂起线程,Thread.Suspend方法可以被当前线程或其他线程调用,而Thread.Sleep(0)只能由当前线程在执行体中调用。当线程用Thread.Suspend挂起时,必须用Thread.Resume方法恢复。不论Thread.Suspend方法调用了多少次,只要调用Thread.Resume方法一次就可以线程恢复执行。用Thread.Suspend方法并不会阻塞线程,调用立即返回。而Thread.Sleep(0)则会阻塞线程。所以确切地说Thread.Sleep(0)暂停线程,而不是挂起线程。

使用Thread.Abort方法可以终止正在执行的线程。当Thread.Abort方法被调用时,线程不会立即终止执行。运行环境将会等待,直到线程到达文档中所描述的“安全点”。如果要确保线程已经完全停止,可以使用Thread.Join方法。这是一个同步调用,同步调用意味着直到线程完全停止,调用才会返回。

Thread.Priority属性用于设置的线程的优先级。其值是Thread.ThreadPriority枚举值,可以设为Highest, AboveNormal,Normal, BelowNormal, Lowest。缺省值是Thread.ThreadPriority.Normal。

线程的同步是为了解决多个线程同时使用同一对象产生的一些问题。通过同步,可以指定代码的临界区(critical section),一次只有一个线程可以进入临界区。使用System.Monitor类(锁定与信号量)进行线程同步: using System;using System.Threading;public void SaveData(string text)//线程执行函数或线程执行函数调用的对象的方法 {

...//执行其他一些不需要同步的处理

Monitor.Enter(this);//获取对象的Monitor锁

...//执行需要同步的处理

Monitor.Exit(this);//释放对象的Monitor锁

...//执行其他一些不需要同步的处理

} 说明:当执行Monitor.Enter方法时。这个方法会试图获取对象上的Monitor锁,如果另一个线程已经拥有了这个锁,这个方法将会阻塞(block),直到这个锁被释放。

也可用C#的lock语句来获得和释放一个Monitor锁。上面同步写成:public void SaveData(string text)//线程执行函数或线程执行函数调用的对象的方法 {

...//执行其他一些不需要同步的处理

lock(this)//获取对象的Monitor锁,代码块执行完成后释放Monitor锁

{

...//执行需要同步的处理

}

...//执行其他一些不需要同步的处理 } 也可以使用System.Threading名称空间的Mutex类(互斥类)进行线程同步。与Monitor锁一样,一次只有一个线程能获得一个给定的互斥。但Mutex要慢得多,但它增加了灵活性。例:

using System;using System.Threading;class Database {

Mutex mutex = new Mutex(false);//创建一个互斥,但不立即获得它

//注意:创建互斥在需要同步的方法之外,实际上它只要创建一个实例

public void SaveData(string text)//需要同步的方法

{

mutex.WaitOne();//等待获得互斥

...//需要同步的处理

mntex.Close();//释放互斥

} } Mutex类重载了三个构造函数:

Mutex()

//创建并使创建类立即获得互斥

Mutex(bool initiallyOwned)

//创建时可指定是否要立即获得互斥 Mutex(bool initiallyOwned, string muterName)//还可以指定互斥的名称 Mutex.WaitOne方法也重载了三次: Mutex.WaitOne()

//一直等待

Mutex.WaitOne(TimeSpan time, bool exitContext)//等待TimeSpan指定的时间 Mutex.WaitOne(int milliseconds, bool exitContext)//等待指定的毫秒 线程的用法:

1)并发操作:比如一个程序监视多个COM口,当每个COM接到信息时执行一段处理时。2)复杂长时间操作:一个长时间的复杂操作可能会使界面停滞,停止用户响应,如果还允许用户停止它,或者显示进度条、显示操作执行进程信息时。

反射(Reflection)就是能够在运行时查找类型信息,这是因为.NET编译的可执行(PE)文件中包括MSIL和元数据(metadata)。

反射的中心是类System.Type。System.Type是一个抽象类,代表公用类型系统(Common Type System, CTS)中的一种类型。

using System;using System.Reflection;//反射命名空间,必须引用 public static void Main(string[] args){

int i = 6;

Type t = i.GetType();

//根据实例得到类型

t = Type.GetType(“System.Int32”);//根据类型的字符名称得到类型

} 通过Assembly类可以得到已经编译.NET Framework程序的中所有类型,例: using System;using System.Diagnostics;//为了使用Process类 using System.Reflection;//为了使用Assembly类 class GetTypesApp {

protected static string GetAssemblyName(string[] args)

{

string assemblyName;

if(0 == args.Length)//如果参数为空,取当前进程的名称

{

Process p = Process.GetCurrentProcess();

assemblyName = p.ProcessName + “.exe”;

}

else

assemblyName = args[0];//取第一个参数,即当前运行程序名

return assemblyName;

}

public static void Main(string[] args)

{

string assemblyName = GetAssemblyName(args);

Assembly a = Assembly.LoadFrom(assemblyName);//调用编译程序集

Type[] types = a.GetTypes();

//得到多个类型

foreach(Type t in types)

//遍历类型数组

{

...//取得t.FullName,t.BaseType.FullName等类型信息

}

} } 一个应用程序可以包括多个代码模块。若要将一个cs文件编译一个模块,只要执行下面的命令:

csc /target:module 要编译的模块.cs //csc是C Sharp Compiler(C#编译器)然后在应用程序中using编译的模块.cs中的NameSpace即可应用了。要反射应用程序中所有代码模块(Module),只要:

Assembly a = Assembly.LoadFrom(assemblyName);//应用程序的物理文件名 Module[] modules = a.GetModules();foreach(Module m in modules){...//显示m.Name等

} 后期绑定(latebinding),例:

string[] fileNames = Directory.GetFiles(Environment.CurrentDirectory, “*.dll”);foreach(string fileName in fileNames){

Assembly a = Assembly.LoadFrom(fileName);

Type[] types = a.GetTypes();

foreach(Type t in types)

{

if(t.IsSubclassOf(typeof(CommProtocol)))//判断是否有CommProtocol的派生类

{

object o = Activator.CreateInstance(t);//生成实例

MethodInfo mi = t.GetMethod(“DisplayName”);

mi.Invoke(o, null);

//调用方法

}

} } //带参数的例子

namespace Programming_CSharp {

using System;

using System.Reflection;

public class Tester

{

public static void Main()

{

Type t = Type.GetType(“System.Math”);

Object o = Activator.CreateInstance(t);

// 定义参数类型

Type[] paramTypes = new Type[1];

paramTypes[0]= Type.GetType(“System.Double”);

MethodInfo CosineInfo = t.GetMethod(“Cos”, paramTypes);

//设置参数数据

Object[] parameters = new Object[1];

parameters[0] = 45;

//执行方法

Object returnVal = CosineInfo.Invoke(o, parameters);

Console.WriteLine(“The cosine of a 45 degree angle {0}”, returnVal);

}

} } 动态生成代码和动态调用的完整例子: //动态生成代码的部分 using System;using System.Reflection;using System.Reflection.Emit;//动态生成代码必须引用 namespace ILGenServer {

public class CodeGenerator

{

public CodeGenerator()

{

currentDomain = AppDomain.CurrentDomain;//得到当前域

assemblyName = new AssemblyName();//从域创建一个程序集

assemblyName.Name = “TempAssembly”;

//得到一个动态编译生成器,AssemblyBuilerAccess.Run表示只在内存中运行,不能保存

assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilerAccess.Run);

//从编译生成器得到一个模块生成器

moduleBuilder = assemblyBuilder.DefineDynamicModule(“TempModule”);

//模块生成器得到类生成器

typeBuilder = moduleBuilder.DefineType(“TempClass”, TypeAttributes.Public);

//为类添加一个方法

methodBuilder = typeBuilder.DefineMethod(“HelloWord”, MethodAttributes.Public, null, null);

//为方法写入代码,生成代码必须使用到IL生成器

msil = methodBuilder.GetILGenerator();

msil.EmitWriteLine(“Hello World”);msil.Emit(OpCodes.Ret);//最后还需要编译(build)一下类 t = typeBuilder.CreateType();

}

AppDomain currentDomain;

AssemblyName assemblyName;

AssemblyBuilder assemblyBuilder;

ModuleBuilder moduleBuilder;

TypeBuilder typeBuilder;

MethodBuilder methodBuilder;

ILGenerator msil;

object o;

Type t;

public Type T

{

get

{

return this.t;

}

}

} } //动态调用的部分

using System;using System.Reflection;using ILGenServer;//引用动态生成代码的类 public class ILGenClientApp {

public static void Main({

CodeGenerator gen = new CodeGenerator();//创建动态生成类

Type t = gen.T;

if(null!= t)

{

object o = Activator.CreateInstance(t);

MethodInfo helloWorld = t.GetMethod(“HelloWorld”);//为调用方法创建一个MethodInfo

if(null!= helloWorld)

{

helloWorld.Invoke(o, null);//调用方法

}

}

} } 调用DLL using System;using System.Runtime.InteropServices;//为了使用DLLImport特性

class PInvokeApp {

[DllImport(“user32.dll”, CharSet=CharSet.Ansi)] //CharSet.Ansi指定Ansi版本的函数(MessageBoxA),CharSet.Unicode指定Unicode版本的函数(MessageBoxW)

static extern int MessageBox(int hWnd, string msg, string caption, int type);//声明DLL中的函数

//[DllImport(“user32.dll”, EntryPoint=“MessageBoxA”)] //用这种方法使用不同的函数名

//static extern int MsgBox(int hWnd, string msg, string caption, int type);

//[DllImport(“user32.dll”, CharSet=CharSet.Unicode)] //调用Unicode版的DLL函数

//static extern int MessageBox(int hWnd, [MarshalAs(UnmanagedType.LPWStr)]string msg,// [MarshalAs(UnmanagedType.LPWStr)]string caption, int type);//将LPWStr翻译为string型,缺省情况系统只将LPStr翻译成string

public static void Main()

{

MessageBox(0, “Hello, World!”, “CaptionString”, 0);//调用DLL中的函数

} } 例2,使用回调: class CallbackApp {

[DllImport(“user32.dll”)]

static extern int GetWindowText(int hWnd, StringBuilder text, int count);

delegate bool CallbackDef(int hWnd, int lParam);

[DllImport(“user32.dll”)]

static extern int EnumWindows(CallbackDef callback, int lParam);

static bool PrintWindow(int hWnd, int lParam)

{

StringBuilder text = new StringBuilder(255);

GetWindowText(hWnd, text, 255);

Console.WriteLine(“Window Caption: {0}”, text);

return true;

}

static void Main()

{

CallbackDef callback = new CallbackDef(PrintWindow);

EnumWindows(callback, 0);

} } 关键字unsafe指定标记块在非控环境中运行。该关键字可以用于所有的方法,包括构造函数和属性,甚至还有方法中的代码块。关键字fixed负责受控对象的固定(pinning)。Pinning是一种动作,向垃圾收集(Garbage Collector, GC)指定一些不能被移动的对象。为了不在内存中产生碎片,.NET运行环境把对象四处移动,以便于最有效地利用内存。使用fixed后指定对象将不会被移动,所以就可以用指针来访问它。

C#中只能得到值类型、数组和字符串的指针。在数组的情况下,第一个元素必须是值类型,因为C#实际上是返回一个指向数组第一个元素的指针,而不是返回数组自身。& 取一个变量的内存地址(即指向该变量的指针)* 取指针所指变量的值-> 取成员

例:using System;class UnsafeApp {

public static unsafe void GetValues(int* x, int* y)

{

*x = 6;

*y = 42;

}

public static unsafe void Main()

{

int a = 1;

int b = 2;

GetValues(&a, &b);

} } fixed语法为:fixed(type* ptr = expression)statements其中type也可以为非控类型,也可是void;expression是任何产生一个type指针的表达式;statements是应用的代码块。例: fixed(int* f = &foo.x)//foo是Foo类的一个实例,x是Foo类的一个int属性 {

SetFooValue(f);//SetFooValue方法的定义为unsafe static void SetFooValue(int* x)} 传统的COM组件可以通过互操作层(COM Interop)与.NET运行环境交互。互操作层处理在托管运行环境和非托管区域中的COM组件操作之间传递所有的消息。

要使COM组件能在.NET环境中使用,必须为COM组件生成元数据。.NET运行环境用元数据层业判断类型信息。在运行时刻使用类型信息,以便生成RCW(Runtime Callable Wrapper,运行时可调用包装)。当.NET应用程序与COM对象交互时,RCW处理对COM对象的装载和调用。RCW还完成许多其他的工作,如管理对象标识、对象生存周期以及接口缓冲区。对象生存周期管理十分关键,因为.NET GC把对象到处移动,并且当对象不再使用时,自动处理这些对象。RCW服务告诉.NET,应用程序正与托管.NET组件交互,同时又使非托管COM组件“觉得”COM对象是被传统的COM客户端调用的。

为了为COM组件生成元数据包装,必须使用tlbimp.exe(TypeLib Importer)工具: tlbimp some_COM.tlb /out:som_COM.dll

第四篇:c#读书笔记

1、.NET平台包括.NET框架和.NET开发工具等组成部分。.NET框架是整个开发平台的基础,包括公共语言运行库和.NET类库。.NET开发工具包括Visual Studio.NET集成开发环境和.NET编程语言。.NET框架(.NET Framework)是.NET开发平台的基础。.NET框架提供了一个跨语言的、统一的、面向对象的开发和运行环境。

2、在Visual Studio.NET集成开发环境下,可以开发多种不同类型的应用程序。最常见的有以下几种。

。控制台应用程序

。Windows应用程序

。ASP.NET网站

3、开发和运行控制台应用程序

创建一个控制台应用程序,主要包含以下步骤:

(1)执行文件—》新建—》项目

(2)打开“新建项目”对话框,在“项目类型”列表中选择Visual c#节点下的Windows,在“模板”窗格中选择“控制台应用程序”项目模板,输入项目的名称、位置及

解决方案名称后,单击“确定”按钮。

(3)在打开的.cs文件中编写代码。

(4)运行程序。执行“调试”—》启动调试菜单命令,编译并运行程序

4、c#程序的基本结构

。using关键字的功能是用于导入其它命名空间中定义的类型,包括.NET类库。例如,代码中使用的console.readline方法实际上是一个简写,其全称是system.console.readline,但由于在代码的开始使用using指令引入了system命名空间,所以后面可以直接使用console.readline来进行输入。

。namespace 即“命名空间”,也称“名称空间”。命名空间是Visual Studio.NET中的各种语言使用的一种代码组织的形式,当编译一个解决方案时,系统会用项目名称做名字,生成一个namespace,并把类都放在这个namespace里面。

第五篇:一个C#初学者的学习心得体会

一个C#初学者的学习心得体会

1.多看多写

看一下别人写的代码,会养成一个好的编程习惯。但更重要的是,要看一下比较成熟的代码。

2.多编多敲

看了代码,就要写代码,可以跟他们相同。这是了解他们的代码,也了解代码的执行过程。特别是在编译的时候,你会发现你的进步和不足。在失败中取得微小的成功,是一件很快乐的事情。

在敲代码的时候,你会发现,你的很多英文都会输入错误。尽量多用“.”这个神奇的点,实质就是调用。

3.简单编程

不要一开始就是很困难、好多行的代码。这样你的自信心会被削弱的。自尊会被打击的。从最基本的学起。

从一开始就慢慢体会代码重复利用的快乐。毕竟这样很节省代码的输入量,而且很能体现你的学习的效果。

4.多多交流

也许很简单的问题,都是一些很简单的属性设置的问题,或许一些你很想不到的边边角角的问题,你总是会感到迷茫,但是,不要担心,你要充分利用帮助文件和网络的资源。

特别是,在学习C#的时候,很多人,很懒得安装MSDN,确实,那些占用很多空间。但那里面有很多好东西,会教你很多的属性的资

料和很多方法。

通过网络的搜索,很会找到很多有关的话题的解决方法,很多你遇到的问题,很有可能,早就被人发现和被人解决。你会在寻找问题的答案中,获得进步。发现问题和解决问题本身,就是一大进步。

5.发现新思路

编程最麻烦的就是套用老方式和老办法。你可以充分利用现有的对象,进行细化和增加新的属性。创新是编程最大的灵感。

6.编程模式

编程归根结底就是对控件属性的修改的过程,使之符合我们的需要。控件也叫做对象,你跟用户最直接的接触方式。修改的过程也就是函数的应用。

通过对现有的控件的学习,你会发现,这些很基本,但是覆盖的面十分的宽广。也许,这些控件可能无法满足你的需要,你就会新建新的控件,来满足新的需要。

但是,基本的控件你是必须要掌握的。

7.善于总结

在总结中,你会发现,你有很大的进步,也存在很多的不足。所以,你就会千方百计的改进你的工作方式和学习方法,使之不断进步。

编程本身是一项创造性的工作。灵感来自客户的需要,来自市场的需要,来自用户的便捷操作,来自您对自己的信心。

8.创造完美

完美是合作的结晶。通过团队的努力奋斗,你会发现你的工作量

减少了,你的质量提高了,你的效率提升了,你的能力增强了。

更重要的事,从你组织和分配中获得的成功,会让你获得鼓励,在今后的编程生活中,体验编程的快乐,从自己做起,分享自己的快乐,从团队合作做起。

总之,自己一直是一位初学者,有很多专业的概念,我还是很不明白,这次,我通过编程实训,使我了解了很多,学习了很多。

下载C#心得体会(5篇模版)word格式文档
下载C#心得体会(5篇模版).doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    C#作业参考答案

    语句while(x>10 && x......

    C#课程设计报告书

    :课程设计报告书 面向对象方法学 课 程 设 计 报 告 设计题目:学生信息管理系统课程 班 级:13软件工程1班 学 号:20130*** 姓 名:何** 指导教师:庄**老师 设计时间:2014年12月 1 附......

    C#程序设计实验报告

    实验报告书写要求实验报告原则上要求学生手写,要求书写工整。若因课程特点需打印的,标题采用四号黑体,正文采用小四号宋体,单倍行距。纸张一律采用A4的纸张。 实验报告书写说明......

    C# 注释规范

    C# 注释(Comment)规范 注释规范包括:模块(类)注释规范、类的属性、方法注释规范、代码间注释 1. 模块(类)注释规范 模块开始必须以以下形式书写模块注释: /// ///模块编号: ///作用......

    C#实习总结

    现在的社会日新月异,科技飞速发展,但是随之而来的环境问题也日益严重,当然这也有很多其他诸如人口、能源等因素,不过这些让人们越来越重视绿色产业,而软件就是首当其冲的一个。我......

    c#基础总结

    【1】面向对象程序设计语言的三大特点是什么?答:【23】Main函数特点?答:1)Main方法是C#程序的限定,默认的为private【2】三种命名法则的特点?答:匈牙利命名法:在变限定符,返回类型为vo......

    C#期末总结

    C#期末总结 接触C#已经有半学期时间,对C#感触颇多。C#作为逻辑性极强,功能强大的程序编程语言,仅仅学习半学期是远远不够的,希望自己能在这条路上不断前行,能够活到老学到老。跟......

    C#学习心得(五篇材料)

    C#速成 一、 绪论 C#是这样的一种语言,具有C++的特点,象Java一样的编程风格, 并且象Basic一样的快速开发模型。如果你已经知道了C++,本文会在不到一个小时的时间内让你迅速掌......