C#笔记

来源:互联网 发布:java新技术论坛 编辑:程序博客网 时间:2024/05/23 00:07

原义字符串以 @ 开头并且也用双引号引起来。
原义字符串的优势在于 不 处理转义序列,因此很容易写入,例如完全限定的文件名就是原义字符串:
@"c:/Docs/Source/a.txt"  // rather than "c://Docs//Source//a.txt"

若要在一个用 @ 引起来的字符串中包括一个双引号,请使用两对双引号:
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.

1. using关键字, using namespace  , using system  ;
   using myalias = mynamespace ;  定义别名
2.console.readline(),用于使程序在执行完上面的代码后不立即退出,在用户按回车键之后才退出程序
3.C# 支持采用中文作为标识符
4.使用关键字作为标识符时,在关键字前加“@”
5.数据类型之间的转换: 强制类型装换 ; ToString  ; Convert类  ;
6.C#中不存在全局变量 。但是可以用另外一种技术实现类似于全局变量的方法,即静态类和静态变量。static  。
7.如果希望程序不进行溢出检测,则可以使用关键字 unchecked ;
8.C#中可以使用 is 关键字进行类型检测。
9.命令窗口调试:视图 --其他窗口--命令窗口 。输入 immed ,进入临时窗口。
10. C#中有一个关键字sizeof ,用于检测关键字的容量大小。
11.Console.WriteLine("{0}{1}{2}{3}...") ,分别代表第一个,第二个 。。。变量。
12.隐型局部变量 。“var”关键字,允许开发者建立一个变量,但不必明确变量的类型,编译器会实现自动类型转换。
13. | 逻辑或运算  ,|| 条件逻辑或运算 。
14.goto语句 ; goto是C#中的一个关键字,goto语句的功能将程序控制权直接传递给标记语句。语句标记为  :
14. 方法的注释,///开始 ,可以形成产品文档 。
15.ref 关键字使参数按引用传递。若要使用ref参数,则定义方法和调用方法都必须显式的使用ref关键字。在调用时,传递到ref参数的参数必须最先初始化。
16.out关键字会导致参数通过引用来传递,这与ref关键字类似,不同的是ref关键字要求变量在传递之前进行初始化。若要使用out参数,定义方法和调用方法也都必须显式的使用out关键字。  (ref修饰的参数作为输入参数,out修饰的参数作为输出参数)。
17.在变量作用域的问题上for循环与一个方法相当。
  for循环中定义的变量在for循环外是非法的。
  在for循环外定义的变量,必须先进行初始化,然后才可以在for循环内使用。
在C#中,只有在声明变量并且对其进行初始化时才会为其进行分配内存。当在for循环内部进行初始化时,变量的作用域在for循环的内部。当在外部初始化改变量时,保证变量的范围在main方法内,因此可以保证for循环正确使用。
18.方法的重载:1)参数类型重载的方法 2)参数引用重载的方法。(以参数带ref和不带ref来调用不同的方法) 3)参数个数重载。根据参数个数的不同调用不同的方法。
19.当Main方法定义在两个类中的时候,可以通过在vs中设置程序入口点,解决Main方法冲突问题。项目--属性 ,应用程序 - 启动对象 。
20.Main方法的参数,可在项目--属性 ,调试 里加入 启动参数  。
21.Main方法的注意事项:必须为静态,而不应为公共的,而且可以具有void 或int返回类型。声明main方法时,即可以使用参数,也可以不使用参数。
22.扩展方法:
public static string toStr1(this int x)
{
    return x.ToString();
}
类必须使用静态类 ;扩展方法必须使用static关键字定义;扩展方法的第一个参数前,必须有this关键字。
静态方法在调用时,必须指明方法所在的类,而扩展方法调用时,直接使用变量的toStr1方法即可。扩展方法已经绑定到参数指定的类型上面。
23.“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。

所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。 该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。可以将此表达式分配给委托类型,如下所示:

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}
///////////////////////////////////////////////
(input parameters) => expression
只有在 Lambda 有一个输入参数时,括号才是可选的;否则括号是必需的。两个或更多输入参数由括在括号中的逗号分隔:(x, y) => x == y

有时,编译器难于或无法推断输入类型。如果出现这种情况,您可以按以下示例中所示方式显式指定类型:(int x, string s) => s.Length > x

使用空括号指定零个输入参数:() => SomeMethod()

24.异常类try ... catch 语句 。
    还可以在代码中编写抛出异常的语句,方法是使用throw关键字。
   finally 代码块用于清除try代码块中分配的任何资源,以及运行任何代码(即使发生异常时也必须执行代码)。finally代码块总是会被执行。

25.类 :定义属性。通过属性可以方便的访问和修改字段的值,通常属性包括get代码块和set代码块。get块用于访问字段值,set块用于设置字段值。同时,属性也可以不对字段进行任何操作。set代码块中的value表示调用属性的代码中属性被赋的值。

26.如果不书写任何访问修饰符时,默认 采用private进行修饰。
  protected关键字是一个受保护成员访问修饰符。受保护成员在他的类中可访问并且可由派生类访问,这是一个介于public和private之间的修饰符。
  internal 关键字是类型和类型成员的访问修饰符。只有在同一个程序集的文件中,内部类型或成员才是可访问的。
27.继承关系使用在类名后面依次加冒号、基类名的方法表示。
28.this关键字用于访问当前类中的各个元素。
29.在现有项目中添加新类的方法 :
  1)解决方案管理器 --添加--类 。
  2)解决方案管理器 --添加--新建项 ,类图 。将自动打开类设计器,在工具箱中也出现类设计器,将工具箱中的内容拖到设计图上可以添加相应的内容,在类结构图上右击,可添加其他属性,方法,构造函数,析构函数等。
30.枚举是一个指定的常数,其基础类型可以是除char以外的任何整形。如果没有显式声明基础类型,则使用int32 。枚举类型有名称,基础类型和一组字段。基础类型必须是一个内置的整形,字段是静态文本字段,其中的每一个字段都表示常数。同一个值可以分配给多个字段,当出现这种情况时,必须将其中某个值标记为主要枚举值,以便进行反射和字符串转换。默认情况下,枚举中定义的值是根据定义的顺序从0开始顺序递增的。
31.结构可以包含构造函数,常量,字段,方法,属性,索引器,运算符,事件和嵌套类型。
32.结构的初始化:1)单个成员初始化
              2)使用构造函数。和类的构造函数基本相同。
public Student(int m_id , string m_name , string m_school)
{
    id = m_id ;
    name = m_name ;
    school = m_school ;
}

Student mystudent1 = new Student(1,“li”,“hnu”);

33.结构的方法:同类基本相同。当用new关键字创建变量时,调用构造函数,不使用new时,不用构造函数。

34.结构和类的区别:
    1)结构是值类型,在堆栈上分配地址,所有的基本类型都是结构类型。
       类是引用类型,在堆上分配地址。
    结构是值类型,所以结构之间的赋值可以创建新的结构,而类是引用类型,类之间的赋值只是复制引用。   
尽管结构的初始化也使用了new关键字,但是结构对象依然分配在堆栈上,如果不使用new,那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用。   
    2)结构,不可继承。
       类:可以继承。

    3)内部结构。
    结构:没有 默认构造函数,没有析构函数。没有abstract和sealed(因为不能    继承),不能有protected修饰符,可以不使用new初始化。在结构中初始化实例    字段是错误的。
35.数组定义: int[] array = {1,2,3} ;int[] array = new int[3] ;
        int[,] array = new int[2,2] ;
36.交错数组: 这种数组的元素是数组。交错数组元素的维数和纬度大小可以不同。
        int[][] array = new int[3][] ;此数组由三个元素组成,每个元素都是一个数组。同样,访问交错数组中的元素必须对其进行初始化:
            array[0] = new int[2] ;
            array[1] = new int[2] ;
            array[2] = new int[2] ;
37.数组的遍历 :foreach语句。foreach(int number in array) ; 数组
                foreach(int[] number in array) ;二维
                number是自定义的,代表arrary中的元素。

38.数组清空:arrary.Clear() ;
        public static void Clear(Arrary arrary ,int index ,int length) ;  起始索引,长度 。

39.数组的查找 : Arrary.IndexOf 和Arrary.LastIndexOf ;数组排序:Arrary.Sort
        Arrary.Reverse ;
40.ArraryList 动态数组 。
41.Hashtable 是以一种键值对形式存在的,因此要通过键来访问Hashtable中的值,即Hashtable[key] .
42.Queue :先进先出
43.Stack :先进后出
44.SortedList:提供了类似于ArraryList 和Hashtable的特性,可以将其理解为一种结合体。SortedList表示键值对的集合,这些键值对按键排序并可按照键和索引访问。
45.Dictionary :字典类,提供了从一组键到一组键的映射。
    遍历Dictionary通常采用foreach语句,此时需要认识另外一个类KeyValuePair    ,该类用来表示Dictionary中的条目。
46.接口不负责功能的实现,只负责功能的定义,而类负责功能的具体实现。
Interface IMyInterface     {     }
    通常使用I加英文单词的方式定义接口的名称。
    接口和类的区别:
    1)接口可以用任何可访问性来声明,但接口成员必须全都具有公共可访问性。也就是说定义接口的成员时不能使用访问修饰符。
    2)不能向成员接口自身附加安全性权限。不能使用static,virtual,abstract和sealed来定义。
    3)接口不能定义构造函数。   
    4)接口中不允许定义字段。
47.接口同类一样,接口之间允许继承。显然,类也可以从接口继承。
48.类可以继承于一个类,C#不允许类之间的多重继承。类可以继承多个接口,类还可同时继承类和接口。
49.在实际应用中,可以将类作为参数传递到方法中,接口同样可以作为参数应用。
50.接口同样可也作为返回值。如果在多重继承中出现名称冲突问题。可以采用显式的方法解决名称冲突的问题。
51.抽象类的用途是提供多个派生类可共享的基类的公共定义,并使用abstract关键字定义。使用abstract关键字不仅可以创建仅用于继承用途的类,也可以定义类成员,即定义派生的非抽象类的功能。
abstract class Class1    {    }
抽象类的用途与接口很相似,抽象类也不能实例化,这点和接口相同,但抽象类中可以定义方法的实现。可以把抽象类看做接口和普通类的结合。
52.抽象类中可以定义抽象方法,其定义方法为在所定义的方法前加abstract关键字。但是抽象成员不能是私有的。必须加public
              abstract public  void SayHello() ;
抽象成员没有实现,否则,编译器报错。但抽象类的派生类必须实现所有抽象方法。要实现抽象成员,必须使用override关键字,并且该成员不能为私有的。
53.密封类可以用来限制扩展性。当在程序中密封了某个类时,其他类不能从该密封类继承。使用密封类可以防止对类进行自定义,这种特性在某些情况下与面向对象编程技术的灵活性和可扩展性是相抵触的。通常不建议使用密封类。
密封类的定义是通过sealed关键字实现的。
        sealed class MySealedClass    {    }
密封类不能作为基类。
由于密封类的不可继承性,因此,他也不能是抽象类。密封类的主要作用是用于防止派生。密封类的这种特性使其从不作为基类,因此对密封类成员的调用速度略快。
    还可以在重写基类中的虚方法或虚属性的方法或属性上使用 sealed 修饰符。 这将使您能够允许类从您的类继承,并防止它们重写特定的虚方法或虚属性。
    当在类中定义新的方法或属性时,通过不将这些方法或属性声明为 virtual,可防止派生类重写这些方法或属性。
    将 abstract 修饰符用于密封类是错误的做法,因为抽象类必须由提供抽象方法或属性的实现的类继承。
    当应用于方法或属性时, sealed 修饰符必须始终与 override 一起使用。
由于结构是隐式密封的,因此它们不能被继承。

54.is运算符用于检测对象是否与给定类型兼容。
   as运算符用于在兼容的引用类型之间执行转换。与强制转换不同,as运算符不会引发错误。当转换失败时,运算符将产生空值,而不是引起异常。
55.virtual关键字用于修饰方法,属性,索引器或事件声明,并且允许在 派生类中重写这些对象。被 virtual修饰的方法(虚方法)可以被任何继承他的类重写。要扩展或修改继承的方法、属性、索引器、事件的抽象实现或虚实现,必须使用override关键字。
C#允许派生类包含与基类方法名称相同的方法,但必须:
    1)基类方法必须定义为virtual
    2)如果派生类的方法前没有new 或override关键字,则编译器将发出紧告,该方法将和存在new关键字一样执行操作。
    3)如果派生类中的方法前面带有new关键字,则该方法被定义为独立于基类的方法。
    4)如果派生类中的方法前面带有override关键字,则派生类的对象将调用该方法,而不调用基类方法。
    5)可以从派生类中用base关键字调用基类方法。
    6)override,virtual和new关键字还可以用于属性,索引器和事件中。

56.使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。
static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型。
常数或者类型声明隐式地是静态成员。
不能通过实例引用静态成员。然而,可以通过类型名称引用它

尽管类的实例包含该类所有实例字段的单独副本,但每个静态字段只有一个副本。
不可以使用 this 来引用静态方法或属性访问器。
如果对类应用 static 关键字,则该类的所有成员都必须是静态的。
类和静态类可以有静态构造函数。静态构造函数在程序开始和类实例化之间的某个时刻调用。

静态类与非静态类基本相同,但存在一个区别:静态类不能实例化。 也就是说,不能使用 new 关键字创建静态类类型的变量。 因为没有实例变量,所以要使用类名本身访问静态类的成员。例如,如果名为 UtilityClass 的静态类有一个名为 MethodA 的公共方法,则按下面的示例所示调用该方法:UtilityClass.MethodA();

下表介绍静态类的主要特性:

仅包含静态成员。

无法实例化。

是密封的。

不能包含 实例构造函数。

因此,创建静态类与创建仅包含静态成员和私有构造函数的类基本相同。私有构造函数阻止类被实例化。使用静态类的优点在于,编译器能够执行检查以确保不致偶然地添加实例成员。编译器将保证不会创建此类的实利。

静态类是密封的,因此不可被继承。它们不能从除 Object 外的任何类中继承。 静态类不能包含实例构造函数,但可以包含静态构造函数。如果非静态类包含需要进行重要的初始化的静态成员,也应定义静态构造函数。

非静态类可以包含静态的方法、字段、属性或事件。即使没有创建类的实例,也可以调用该类中的静态成员。始终通过类名而不是实例名称访问静态成员。无论对一个类创建多少个实例,它的静态成员都只有一个副本。静态方法和属性不能访问其包含类型中的非静态字段和事件,并且不能访问任何对象的实例变量(除非在方法参数中显式传递)。

更常见的做法是声明具有一些静态成员的非静态类,而不是将整个类声明为静态类。静态字段有两个常见的用法:一是记录已实例化对象的个数,二是存储必须在所有实例之间共享的值。

静态方法可以被重载但不能被重写,因为它们属于类,不属于类的任何实例。

虽然字段不能声明为 static const,但 const 字段的行为在本质上是静态的。 这样的字段属于类型,不属于类型的实例。因此,可以同对待静态字段一样使用 ClassName.MemberName 表示法来访问 const 字段。 不需要对象实例。

C# 不支持静态局部变量(在方法范围内声明的变量)。

通过在成员的返回类型之前使用 static 关键字可以声明静态类成员

静态成员在第一次被访问之前并且在调用静态构造函数(如有存在)之前进行初始化。若要访问静态类成员,应使用类名而不是变量名来指定该成员的位置

57.属性:属性是类中除方法之外另一种可以对字段进行操作的“方法”。尽管技术上属性和方法非常类似,但使用上却有很大的差别。
只读属性:只提供get访问器,而不编写set部分。
属性中可以包含代码。属性中的代码可以进行对属性的赋值和读取进行控制,检测等很多工作。
58.迭代器:迭代器似的开发人员能够实现在类或结构中支持foreach迭代,而不必实现整个IEnumberable接口。
迭代器概述:
迭代器是可以返回相同类型的值的有序序列的一段代码。

迭代器可用作方法、运算符或 get 访问器的代码体。

迭代器代码使用 yield return 语句依次返回每个元素。 yield break 将终止迭代。

可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示: foreach(int x in SampleClass.Iterator2){}。

迭代器的返回类型必须为 IEnumerable、 IEnumerator、 IEnumerable <(Of <(T >)>) 或 IEnumerator <(Of <(T >)>)。

迭代器是 LINQ 查询中延迟执行行为的基础。

yield 关键字用于指定返回的一个或多个值。 到达 yield return 语句时,会保存当前位置。 下次调用迭代器时将从此位置重新开始执行。

迭代器对集合类特别有用,它提供一种简单的方法来迭代复杂的数据结构(如二进制树)。

    创建迭代器最常用的方法是对 IEnumerable 接口实现 GetEnumerator 方法。

public System.Collections.IEnumerator GetEnumerator()
{
    for (int i = 0; i < 10; i++)
    {
        yield return i;
    }
}
GetEnumerator 方法的存在使得类型成为可枚举的类型,并允许使用 foreach 语句。

foreach语句用于访问数组或对象集合中的每个元素,同样也可以用于实现了迭代器的类,但不应用于更改集合内容,以避免产生不可预知的错误。
可以在同一个迭代器中使用多个 yield 语句。

59.分部类:将类、结构或接口的定义拆分到两个或多个源文件中,每个源文件包含类定义的一部分,编译应用程序时,visual studio 2010 会把所有部分组合起来,这样的类被称为分部类。分部类用partial关键字定义。
    代码中在类前加partial 说明该类是一个分部类,虽然没有该分部类的其他部分,但C#任然将其作为分部类处理。但是应该避免这种做法,这样显然会增加.NET Framework的负担,因为.NET Framework将会搜索其他部分。

    各个部分必须具有相同的可访问性,如public ,private 等。

    分部类的两部分都必须用partial限定。
    在类的两个部分分别使其继承不同的类和接口,运行时,.NET Framework能够将其很好的结合。
    partial关键字的位置必须位于紧接class ,interface 以及struct的位置。

60.索引器允许类或结构的实例就像数组一样进行索引。索引器类似于 属性,不同之处在于它们的访问器采用参数。
索引器概述使用索引器可以用类似于数组的方式为对象建立索引。

get 访问器返回值。 set 访问器分配值。

this 关键字用于定义索引器。

value 关键字用于定义由 set 索引器分配的值。

索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。

索引器可被重载。

索引器可以有多个形参,例如当访问二维数组时。

要声明类或结构上的索引器,请使用 this 关键字,如下例所示:

public int this[int index]    // Indexer declaration
{
    // get and set accessors
}
索引器的定义采用访问限定符后跟返回值类型、this关键字、索引参数的形式。其中,索引参数要包含在索引操作符[]中。

61.泛型:
泛型概述使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。

泛型最常见的用途是创建集合类。

.NET Framework 类库在 System.Collections.Generic 命名空间中包含几个新的泛型集合类。 应尽可能地使用这些类来代替普通的类,如 System.Collections 命名空间中的 ArrayList。

您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。

可以对泛型类进行约束以访问特定数据类型的方法。

关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。

62.委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。 您可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。下面的示例演示了一个委托声明:
        public delegate int PerformCalculation(int x, int y);

与委托的签名(由返回类型和参数组成)匹配的任何可访问类或结构中的任何方法都可以分配给该委托。方法可以是静态方法,也可以是实例方法。这样就可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。只要知道委托的签名,就可以分配您自己的方法。
在方法重载的上下文中,方法的签名不包括返回值。但在委托的上下文中,签名的确包括返回值。换句话说,方法和委托必须具有相同的返回值。

将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,可以向排序算法传递对比较两个对象的方法的引用。分离比较代码使得可以采用更通用的方式编写算法。

委托概述委托具有以下特点:

委托类似于 C++ 函数指针,但它们是类型安全的。

委托允许将方法作为参数进行传递。

委托可用于定义回调方法。

委托可以链接在一起;例如,可以对一个事件调用多个方法。

方法不必与委托签名完全匹配。

63.委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。 与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用 字符串作为参数并返回 void 的方法。
public delegate void Del(string message);

构造委托对象时,通常提供委托将包装的方法的名称或使用 匿名方法。 实例化委托后,委托将把对它进行的方法调用传递给方法。调用方传递给委托的参数被传递给方法,来自方法的返回值(如果有)由委托返回给调用方。这被称为调用委托。可以将一个实例化的委托视为被包装的方法本身来调用该委托。例如:
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
    System.Console.WriteLine(message);
}

// Instantiate the delegate.
Del handler = DelegateMethod;

// Call the delegate.
handler("Hello World");

委托类型派生自 .NET Framework 中的 Delegate 类。 委托类型是 密封的,不能从 Delegate 中派生委托类型,也不可能从中派生自定义类。 由于实例化委托是一个对象,所以可以将其作为参数进行传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息。此功能类似于接口所提供的封装。有关更多信息,请参见 何时使用委托而不使用接口。

回调的另一个常见用法是定义自定义的比较方法并将该委托传递给排序方法。它允许调用方的代码成为排序算法的一部分。下面的示例方法使用 Del 类型作为参数:
public void MethodWithCallback(int param1, int param2, Del callback)
{
    callback("The number is: " + (param1 + param2).ToString());
}

然后可以将上面创建的委托传递给该方法:
MethodWithCallback(1, 2, handler);

在控制台中将收到下面的输出:

The number is: 3

在将委托用作抽象概念时, MethodWithCallback 不需要直接调用控制台 -- 设计它时无需考虑控制台。 MethodWithCallback 的作用只是准备字符串并将该字符串传递给其他方法。 此功能特别强大,因为委托的方法可以使用任意数量的参数。

将委托构造为包装实例方法时,该委托将同时引用实例和方法。除了它所包装的方法外,委托不了解实例类型,所以只要任意类型的对象中具有与委托签名相匹配的方法,委托就可以引用该对象。将委托构造为包装静态方法时,它只引用方法。考虑下列声明:
public class MethodClass
{
    public void Method1(string message) { }
    public void Method2(string message) { }
}
加上前面显示的静态 DelegateMethod,现在我们有三个方法可由 Del 实例进行包装。

调用委托时,它可以调用多个方法。这称为多路广播。若要向委托的方法列表(调用列表)中添加额外的方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。例如:

MethodClass obj = new MethodClass();
Del d1 = obj.Method1;
Del d2 = obj.Method2;
Del d3 = DelegateMethod;

//Both types of assignment are valid.
Del allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;

MethodClass obj = new MethodClass();
Del d1 = obj.Method1;
Del d2 = obj.Method2;
Del d3 = DelegateMethod;

//Both types of assignment are valid.
Del allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;

此时, allMethodsDelegate 在其调用列表中包含三个方法 -- Method1、 Method2 和 DelegateMethod。 原来的三个委托 d1、 d2 和 d3 保持不变。 调用 allMethodsDelegate 时,将按顺序调用所有这三个方法。 如果委托使用引用参数,则引用将依次传递给三个方法中的每个方法,由一个方法引起的更改对下一个方法是可见的。如果任一方法引发了异常,而在该方法内未捕获该异常,则该异常将传递给委托的调用方,并且不再对调用列表中后面的方法进行调用。如果委托具有返回值和/或输出参数,它将返回最后调用的方法的返回值和参数。若要从调用列表中移除方法,请使用减法运算符或减法赋值运算符(“-”或“-=”)。例如:

//remove Method1
allMethodsDelegate -= d1;

// copy AllMethodsDelegate while removing d2
Del oneMethodDelegate = allMethodsDelegate - d2;

由于委托类型派生自 System.Delegate,所以可在委托上调用该类定义的方法和属性。 例如,为了找出委托的调用列表中的方法数,您可以编写下面的代码:

int invocationCount = d1.GetInvocationList().GetLength(0);

在调用列表中具有多个方法的委托派生自 MulticastDelegate,这是 System.Delegate 的子类。 由于两个类都支持 GetInvocationList,所以上面的代码在两种情况下都适用。

多路广播委托广泛用于事件处理中。事件源对象向已注册接收该事件的接收方对象发送事件通知。为了为事件注册,接收方创建了旨在处理事件的方法,然后为该方法创建委托并将该委托传递给事件源。事件发生时,源将调用委托。然后,委托调用接收方的事件处理方法并传送事件数据。给定事件的委托类型由事件源定义。有关更多信息,请参见 事件(C# 编程指南)。

在编译时,对分配了两种不同类型的委托进行比较将产生编译错误。如果委托实例静态地属于类型 System.Delegate,则允许进行比较,但在运行时将返回 false。 例如:
delegate void Delegate1();
delegate void Delegate2();

static void method(Delegate1 d, Delegate2 e, System.Delegate f)
{
    // Compile-time error.
    //Console.WriteLine(d == e);

    // OK at compile-time. False if the run-time type of f
    // is not the same as that of d.
    System.Console.WriteLine(d == f);
}

64.事件(Event):类或对象可以通过事件向其他类或对象通知发生的相关事情。 发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件。可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件。IDE 会自动添加空事件处理程序方法和订阅事件的代码。

事件概述事件具有以下特点:

发行者确定何时引发事件,订户确定执行何种操作来响应该事件。

一个事件可以有多个订户。一个订户可处理来自多个发行者的多个事件。

没有订户的事件永远也不会引发。

事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。

如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。要异步调用事件,请参见 使用异步方式调用同步方法。

可以利用事件同步线程。

在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的。

65.button  的 Anchor 属性:用于设置某个控件如何绑定到容器的边缘,以及当容器的大小发生改变时,该控件如何响应。
Cursor属性:用于设置鼠标经过该控件时所显示的样式。
Dock属性可以使控件停靠在容器的边框上。
Image属性:为按钮添加图片 。

66.文本框TextBox的
    CauseValidation:用于验证文本框内容的合法性
    CharacterCasing:用于指示所输入文本的大小写格式。
    MaxLength:文本框所输入字符的长度
    MultiLine:是否接受多行
    PasswordChar:常用语密码输入栏

67.单选框控件RadioButton:在一个容器(如Panel,GroupBox或窗体)内绘制单选按钮即可将他们分组。直接添加到一个窗体中的所有单选按钮将形成一个组。如要添加不同的组,必须将他们放到面板或分组框中。
    Checked属性表示是否选中。
    Apperance属性显示不同的风格。
    常用的事件:Click和CheckChanged两种。
68.复选框控件CheckBox;三种状态:checked ,unchecked ,indeterminate。
    CheckBox::Checked 属性:获取或设置一个值,该值指示 CheckBox 是否处于选中状态。如果 CheckBox 处于选定状态,则为 true;否则为 false。 默认值为 false。
    CheckBox::CheckState 属性:如果 ThreeState 属性设置为 false,则 CheckState 属性值只可以在代码中设置为 CheckState.Indeterminate,而不能通过用户交互来设置。
    CheckBox::ThreeState 属性 :获取或设置一个值,该值指示此 CheckBox 是否允许三种复选状态而不是两种。如果 CheckBox 可以显示三种复选状态,则为 true;否则为 false。 默认值为 false。

69.分组框控件GroupBox:用于为其他控件提供可识别的分组。通常可以用GroupBox控件为RadioButton控件和CheckBox控件提供分组,这样就可以在一个窗体中有几个独立的分组。

70.面板控件Panel:panel控件是另一种类型的控件,用于为其他控件提供可识别的分组。通常,使用面板按功能细分窗体。panel控件类似于groupbox,但只有panel可以有滚动条,只有groupbox可显示标题。

71.链接标签控件LinkLabel。
72.列表框控件ListBox 。
73.可选列表框控件CheckedListBox:  CheckedItems ,Items[i]
74.组合框控件Combobox    : selectedItem
75.微调按钮控件NumericUpDown

76.创建自定义控件:windows窗体控件库 -拖入控件,编写代码,编译。
    在工具箱--常规,右击-选择项 ,浏览 ,找到编译成功的.dll库文件。

77.主菜单MenuStrip ,&F ,快捷键。右击新创建的菜单,可以添加其他内容,如分隔符,图像等。
78.工具栏ToolStrip ;
79.上下文菜单ContextMenuStrip。又叫弹出菜单或右键菜单,都是指在右击相应的控件时弹出的菜单。 添加ContextMenuStrip1后,设置form1的ContextMenu属性为ContextMenuStrip1,运行程序即可。
80.状态栏StatusStrip:再添加StatusLabel ,text属性显示状态信息。
81.windows窗体应用程序分为三类:基于对话框的应用程序,单一文档界面(SDI)应用程序和多文档界面(MDI)应用程序。
82.RichTextBox是一种复杂的文本框,该控件用于显示,输入和操作带有格式的文本。除具有textbox控件的所有功能外,还可以显示字体,颜色和链接,从文件加载文本和嵌入图像,撤销和重复编辑操作,以及查找指定的字符。             

83.多窗口设计:新建项目,将form1 的IsMdiContainer 属性设置为True 。添加新项,windows窗体 form2,
         form2 frm = new form2() ;
         //使新建的form2窗体的父窗口为当前窗体
         frm.MdiParent = this ;
         frm.show() ;

84.使用对话框:从属性上看,对话框是FormBorderStyle属性为FixedDialog的窗体。

85.   打开文件对话框OpenFileDialog
    openFileDialog1.ShowDialog();
    openFileDialog1.Title = "  " ;
    openFileDialog1.InitialDirectory = @"E:/" ;

    openfiledialog 的返回值是dialogresult枚举中的一个,为dialogresult.ok或dialogresult.cancle。
    openfiledialog.multiselect = false ; //是否允许多选
    if(openfiledialog.showdialog()==dialogresult.ok)
    {
    form2 frm = new form2();
    StreamReader sr = new StreamReader(openfiledialog.openfile());
    frm.RichTextBoxText = sr.ReadToEnd() ;
    frm.show() ;
    }

86. 保存文件对话框SaveFileDialog :
    Stream stream = saveFileDialog、openfile();
    streamWriter sw = new streamWriter(stream);
    frmEdit frm = (frmEdit)this. ;
    sw.write(frm.richtextboxtext) ;

87.字体设置对话框FontDialog:

88.窗体和对话框通常有两种状态,分别为模式的和无模式的。模式的窗体或对话框必须关闭或隐藏,然后用户才能继续使用应用程序的其余部分。如果使用ShowDialog方法显示一个窗体,则为模式的;用show方法时,为无模式的对话框。

在窗体2中,formborderstyle改为fixedDialog , 将controlBox 为false 。
按钮 dialogresult 属性可设置为ok ,cancle 。

89.GDI+是.NET中图形编程的高级内容。主要用于在窗体上绘制各种图形图像,可以用于绘制各种数据图形,进行数学仿真等。
Graphics类封装一个GDI+绘图图面。Graphics对象表示GDI+绘图表面(似画布),用于创建图形图像的对象。绘图时,需要先创建Graphics对象,然后才可以使用GDI+绘制线条和形状,呈现文本或显示与操作图像。
    绘制图形包括以下两个步骤:
    1)创建Graphics对象。
    2)使用Graphics对象绘制线条和形状,呈现文本或显示与操作图像。

    创建Graphics对象有三种方法:
    1)在窗体或控件的Paint事件中进行对图形对象的引用,作为PaintEventArgs的一部分。
private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
        }

    2)调用某控件或窗体的CreateGraphics方法以获取对Graphics对象的引用,该对象表示该控件或窗体的绘图图面。如果想在已存在的窗体上或控件上绘图,应该使用此方法。
Graphics g;
g = this.CreateGraphics();

    3)由从Image继承的任何对象创建Graphics对象。此方法在需要更改已存在的图像时十分有用。
Bitmap myBitmap = new Bitmap(@"c:/pic.bmp");
Graphics g = Graphics.FromImage(myBitmap);

    此后,可以应用于绘制线条和形状,呈现文本或显示与操作图像。与Graphics对象一起使用的主要有Pen类,Brush类,Font类,Color类。

    1)Pen使用:
       private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen myPen = new Pen(Color.Blue);
            g.DrawLine(myPen, 100, 100, 200, 200);//画一条直线
            myPen.Dispose();
            g.Dispose();
        }
    2)Font类使用:在窗体上描绘文本,可以借助Font类来实现。可以用Graphics的DrawString方法描绘文本。
        private void button1_Click(object sender, EventArgs e)
        {
            Graphics g = this.CreateGraphics();
            string str = "使用DrawString方法";
             Font myFont = new Font("黑体",20);
             Brush b = new SolidBrush(Color.Blue);
             float x = 50.0f;
             float y = 50.0f;
             StringFormat myFormat = new StringFormat();
             g.DrawString(str, myFont, b, x, y, myFormat);
             myFormat.Dispose();
             myFont.Dispose();
             g.Dispose();
        }
    3)位图类Bitmap类:创建一个Image类的新对象,创建一个Graphics对象类引用要使用的绘图图面,然后调用Graphics对象的DrawImage方法,这样将在图形类所表示的绘图表面上绘制图像。

90.MonthCalendar:可用鼠标拖曳,选择一段连续的时间,使用selectionstart和selectionend表示。
91.DateTimePicker控件:选择日期和时间,只能选择一个时间,而不是连续的时间段。
    DateTimePicker.Value.DayofYear ,本年的第多少天 。

92.TreeView控件:属性选择Nodes属性。
       private void button1_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();

            if (Directory.Exists(textBox1.Text.Trim()))
            {
                //先添加根节点为输入的目录
                treeView1.Nodes.Add(textBox1.Text.Trim());
                //显示根节点所代表的目录下的子文件夹
                PopulateTreeView(textBox1.Text.Trim(),treeView1.Nodes[0]);
            }
            else
            {
                MessageBox.Show(textBox1.Text + "not found ");
            }
        }

        string subStringDirectory;
        public void PopulateTreeView(string directoryValue, TreeNode parentNode)
        {
            //存储目录的子目录,
            // 该方法只返回一级子目录
            // 之后采用递归的方法,列出其所有子目录
            string[] directoryArray = Directory.GetDirectories(directoryValue);
            //列出当前目录的子目录
            // 返回值
            //类型: array            //path 中子目录名称的数组。
            try
            {
                if (directoryArray.Length != 0)
                {
                    //对于每个子目录创建一个节点
                    //对该目录下的文件夹再创建一个节点
                    // 对所有文件夹再执行PopulateTreeView方法,显示其子目录
                    //
                    foreach (string directory in directoryArray)
                    {
                        listBox1.Items.Add(directory);
                        //从完整的路径名中获取尾部的有效文件夹名称
                        // 通过查找“/“实现.
                        // 如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。
                        subStringDirectory = directory.Substring(directory.LastIndexOf('//') + 1, directory.Length - directory.LastIndexOf('//') - 1);
                        //为当目录创建节点
                        TreeNode myNode = new TreeNode(subStringDirectory);
                        //添加当前节点到treeview控件中
                        parentNode.Nodes.Add(myNode);
                        //列出子目录的文件夹
                       // PopulateTreeView(directory, myNode);
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                parentNode.Nodes.Add("Access denied ");
            }
        }

93.TabControl控件通过一个个的标签分门别类的显示不同的内容。

94.Windows媒体播放器
            openFileDialog1.ShowDialog();
            axWindowsMediaPlayer1.URL = openFileDialog1.FileName;
95.LINQ,WPF,WCF ,WF是.NET 3.5 框架新添加的4大组件。其中,LINQ是专门的用户数据查询技术,WPF是微软推出的开发windows客户端程序的下一代工具。WCF是微软为构建面向服务的应用程序而提供的统一编程模型。WF是一个数据流模型,可以部署项目的简要步骤和过程。
Windows Presentation Foundation 是微软推出的下一代显示系统,关键作用是生成能带给用户震撼视觉体验的windows客户端应用程序。
    WPF提供两种应用程序模型,即独立应用程序和用于浏览器承载的应用程序。

96.Windows窗体应用程序与数据库应用
    1)添加BindingSource控件,编辑DataSource属性。
    2)添加数据绑定控件:Textbox ,修改DataBindings属性,使其绑定数据表的某项。
    3)添加BindingNavigator控件,设置BindingSource属性,使其与textbox控件的BindingSource属性相同。即可查询所有表中的记录。

原创粉丝点击