forked from shangerxin/BookNotes
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathC#2008入门到精通_笔记.txt
862 lines (760 loc) · 42.5 KB
/
C#2008入门到精通_笔记.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
.net 3.5已2.0 3.0为基础与之前的 1.0 1.1不同,1.0是相互独立的
功能更新
LINQ, Language Integrate Query,语言集成查询
外接程序的扩展性 System.AddIn.dll可扩展的应用程序集
WPF, Windows Presentation Foundation包含多方面的改进
WCF与Asp.net中的异步JavaScript和XML(ajax)功能
新增了密码类ClickOnce
System.Object是系统顶端类
常见系统程序集
System.dll 用于存储数据类型及基础类
system.windows.forms.dll 窗体控件
system.xml.dll xml文件操作,xml是ADO.net及Internet相关服务的数据传输的主要协议
system.drawing.dll 用于向输出设置绘制各种图形
system.data.dll 用于定义组成ado.net的组件
命名空间
包含类、委托、结构、枚举、接口,他们都是类型
类是引用类型
委托也是引用类型,类似于VC的回调函数,C的函数指针
结构是值类型
枚举是一种受限制的值类型
接口,接口定义了类必须具有的能力
定义命名空间
namespace Name
可以包含句号、隐式具有公共访问权限、可以两次或者多次声明中定义一个命名空间
引用命名空间使用
using Name
using alias = typeNameSpace //当引用了两个具有相同类名的命名空间时可以为另一命名空间起别名
using 指令提供的对象必须实现IDisposable接口
C#有两种可执行的主函数方法
public static void main()
public static int main()
C#编译器使用,.net frameworks sdk的使用
csc *.cs //编译后产生*.exe
csc /target:library *.exe //产生*.dll
csc /out:*.exe *.csc //编译并产生*.exe
csc /define:debug /optimize /out:*.exe *cs //通过优化和定义debug符号,并编译当前所有CS文件为 *.exe
csc /target:library /out:*.dll /warn:0 /nologo /debug *.cs //编译为调试版本dll,切无警告和提示
csc /target:library /out:*.dll *.cs //编译所有CS文件为一个*.DLL
区别于C++编译器的是C#编译器不需要连接器
vsvars32.bat用于在当前文件系统中设置适当的软件配置环境
输出文件类型
/target 或 /t:exe, 控制台程序;/t:library,带有清单的库;/t:module,没有清单的组件;/t:winexe,windows应用程序
编译时调用类库文件
csc *.cs /r:test.dll
变量内建类型
sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, enum-type, reference-type之一(string, object)
常量
public|new|protected|internal|private const type name = value;
XML注释,已/// 开头,在注释中可以吧包含类型和类型成员的文档得XML标识符放置在代码中
可以识别的标识符
<c>一行代码, <code>多行代码, <example>代码示例, <exception>一个异常, <include>包含其它文档说明的注释, <list>列表插入到文档说明, <param>标记方法的参数, <paramref>表示一个单词是一个方法的参数, <permission>说明成员的访问, <remarks>对成员添加描述, <returns>说明方法的返回, <see>提供对另一个参数的交叉引用, <seealso>提供描述中的参见部分, <summary>对类型和成员的小结, <value>描述属性
C#中并没有像C++中的预处理指令
#define simbolName, #if, #elif, #else, #endif; define中定义的符号用if判断真假来判断编译的代码块
#warning, #error
#region, #endRegion 用于为一块代码制定命名空间名
例如
#region private MaxNumber
private int x;
private int y;
#endRegion
#line 用于改变编译器在警告和错误中显示的文件名和行号信息或者要使用某些软件包改变键入的代码
#pragma 提供特殊指令例如 #pragma warning 启用禁用警告,#pragma checksum生成源文件的校验和用于asp.net中
循环语句中添加
foreach( type varName in varCollection )
跳转语句
goto, 同汇编或批处理
值类型与引用类型的区别
值类型 引用类型
内存地点 栈中 堆中
效率 高 低
回收 立即回收 等待GC(garbage collector )回收
CTS类型
.net使用通用类型系统,定义了可以在中间语言(IL)中使用的预定义数据类型
byte 8位、short 16、int 32、long 64
浮点数 float, double 0.5f
字符型 char , C#中字符型为16位,而C++中为8位
财务类型 decimal 5.3421m
C#中允许包含多个main方法,但是要求main方法属于不同的命名空间,编译时需要指定
csc *.cs /main:className.subClass
参数的传递
引用传递使用ref, 值传递,输出参数,参数数组用params修饰符声明
LINQ,语言的查询框架
隐含型化的变量类型:var varName //类似于VB的 variant类型,变量初始化必须为表达式,只适用于局部及块作用域,而且可以用来初始化一些集合元素
var s1 = new {name = "a", price = 2}
var s2 = new {name = "a", price = 2}
且可以使用 s1 = s2 来赋值,编译器使用集合命名顺序来检查类型是否一致
扩展方法,特殊的静态方法,定义在一个静态类中,使用同其他方法一样;定义时与一般的静态方法的区别是第一个参数前加this
public static returnType expFunName( this type sourceObj [,paramenters])
扩展方法就是FLEX中的动态类,可以在其他类的代码中添加已经编写过的类的方法及该方法的实现代码,且该方法是静态的;重新定义该类对象时可以直接使用
例如:
class orgClass; //已定义的类
class expOrgClassCode //用于扩展已定义类的方法
{
public static void ExpFunName( this orgClass orgClassObj ) //定义已定义类的扩展方法
{
//扩展方法的实现
orgClassObj.newProperty = value; //新建扩展方法属性值
console.writeline( orgClassObj.newProperty );
}
}
static void main( string args[] )
{
o = new orgClassObj;
o.ExpFunName(); //直接调用扩展方法
}
对象集合初始化器,Object Initializers和Collection Initialziers
public class Book
{
public string BookName { get;set;}
internal int Num;
}
Book b = new Book{ BookName = "a", Num = 50 }; //对象初始化器允许给internal对象赋值
List<Book> b = new List<Book> //集合初始化器可以少些几个add函数
{
new Book{BookName = "1", Num = 50};
new Book{BookName = "2", Num = 3};
}
/*?/Lambda表达式,可以将其作为内存对象, 形式如下
( [parameters] ) => { statments };
自动属性,可以不定义私有变量,直接使用空的get/set自动在类中生成一个私有成员变量
运算符及类型强制转换
逻辑运算符 &, ^, ~,&&, ||, !
检测运算符 sizeof(检测运算符), is, typeof, as //is 返回bool, as 真返回本身假null
溢出异常控制 checked unchecked
命名空间别名限定 ::
空接合运算符 ?? // y = x ?? 6 如果x是可空类型且为null则 y = 6否则 y = x
条件运算符 ? :
超范围检测 checked(statment), unchecked(statment)
可空类型 type? varName //可空类型与非可空类型不能随意比较
类型转换:
不存在char类型的隐式转换
装箱与拆箱操作
将值类型赋值给object等引用类型,且与C++指针的区别是装箱是赋值操作
经过强制类型转换将object类型转换为指定值类型
对象相等的比较
ReferenceEquals() 两个引用是否指向相同类的判断函数
Equals() 是需实例版本是System.object的虚方法 //用于值类型比较
Equals() 静态的方法,可用于处理一个对象是null的情况
==
运算符重载
public static ClassName operator + ( ClassName varName0, ClassName varName1)
重载 = , !=方法时还需要重载System.Ojbect中继承的Equals() 和 GetHashCode()方法
而重载 == ,必须同时重载 !=
用户自定义类型数据转换,隐式转换
public static implicit operator float( userType value ) //定义隐式类型转换
{
...
return statment
}
public static explicit operator UserType(AimType value ) //定义显示类型转换
{
...
return statment
}
主要是使用convert类实现
注意,如果某一个类直接或者简介继承了某一个类,那么就不能在这两个类之间进行数据类型转换,类似于不能有直系血缘关系
对于类转换只有基类引用的实例是派生类时使用 派生类 = (派生类)基类 强制转换才会成功
如果一定要将基类转换为派生类则最直接的方法就是定义一个基类为参数的派生类构造函数
如果没有基类可以使用.net的公有类进行引用(装箱)
UserType aimTypeObj = new UserType();
object o = aimTypeObj;
UserType b = (UserType)o;
但是o不能第二次强制转换,也就是说.net中的引用只能使用一次
多态性,运行时多态,通过重写虚函数来实现;编译时多态,通过重载来实现两种
总的来说就是一个借口多种方法,一个函数形式同一类的多个类的方法与之对应
参数传递方法,按引用传递,参数名前加入关键字ref。等同于C++中的指针传递,但传递前必须初始化。out方式传递参数,等同于指针传递,但传递参数前无需初始化。
静态方法只能访问静态属性和字段
重载方法,无需添加overwrite关键字
非托管资源如,窗口,文件,网络连接
构造函数与析构函数
构造函数无返回值,应当注意构造函数内的错误捕获
析构函数无法继承或重载,而且一个类只能有一个析构函数,析构函数无修饰符无参数
命名方法同C++
结构
结构不能被继承,结构式是值类型,通常创建速度较快
结构中的默认构造函数不能被替换而类中的的默认构造函数可以被替换
定义时只是将类定义的class替换为struct,可以定义属性,方法,方法函数等。使用时与类无区别,只是在程序的底层并不为结构分配堆空间
继承
继承子类可以重写父类的同名方法,这样做子类的同名函数调用时调用子类方法
派生类中可以使用base关键字来访问基类成员
基类构造函数直接使用 base([parameters])访问
调用基类方法base.FunName([parameters])
可以在代码中使用强制转换的方法来访问基类方法
(baseClass)objChildClass.BaseClassFunctionName([parameters])
虚方法
使用virtual关键字修饰方法、属性、索引器或时间声明。调用虚方法时会调用对象类型合适的方法(特别在使用父类对象引用子类对象时这点特别重要)。重写虚方法的时候需要加上overwrite关键字
虚拟属性的行为与抽象方法是一样,可以在继承中重写虚拟继承属性
注意:virtual不能与static, abstract, private和overwrite关键字一起使用
隐藏基类中的成员
在子类代码声明时增加new关键字来隐藏同名的基类成员
例:
new public void FunName()
抽象类与抽象方法
abstract关键字,子类中可以重写抽象方法或者实现抽象方法
例如
abstract class className{}
public abstract void FunName{};
public overwrite void FunName{} //子类中实现抽象方法
封闭类,防止继承某一类。使用关键字sealed实现
sealed class className{}
封闭方法,可以防止派生类中重写某一方法,但前提是这个方法不是从某一基类继承的,并不能定义为virtual方法
public sealed void funName()
接口,就是一种约定,使得实现结构的类在形式上保持一致。接口不包含字段,使用关键字interface。接口的成员都是公共的。接口可由方法、属性、事件、索引器4种成员类型任意组合构成。
实现接口的类成员必须是共有的、非静态的。类的属性和索引器可以为接口上的定义的成员提供额外的访问器。
接口的使用同继承类一样。
接口与抽象类的区别,抽象类用于部分实现一个类,抽象类用于关系密切的对象。接口是为不相关的对象提供通用的功能。抽象类主要用于设计大的功能单元,接口用于设计小的简练的功能块吧。
接口可以多重继承
数组,格式是java风格
int[] aryName = new int[4]{初始化内容};
int[,] aryName = new int[5,4];
C#中可以定义维数不同的多维数组, C++中的多维指针数组
int[][] num = new int[2][]{new int[]{2,3,4], new int[]{5,6,7,8,8}};
使用foreach语句
foreach( type varName in aryCollection ){}
使用该语句必须保证类型已经实现了IEnumerable接口
而ICollection接口继承自IEnumerable接口
IList接口继承ICollection接口,Array类实现了IList接口,由于IList中定义了Item属性
array类, System.Array,创建数组
排序,数组中的元素调用sort()方法时需要实现IComparable接口
复制,copy()方法类似于c++中的memcpy()方法
而IComparer接口则为对象定义了其他排序的方法,IComparable接口为对象定义了自然排序方法
C#中常用的集合对象有, ArrayList(动态数组)、HashTable(散列表)、BitArray(位数组)、Queue(先进先出的队列)、SortList(有序表)、Stack(栈)、LinkedList<T>
字典,类Dictionary<TKey,Tvalue>,类似于SortList<Tkey,Tvalue>,字典的性能取决于GetHashCode()的实现代码,同时键类型还必须执行IEquality.Equals()方法,或者重写Object的Equals()方法。
其他类型字典
Hashtable, ListDictionary链表实现, HybridDictionary元素少于10使用链表,多余10使用哈希表, NameObjectCollectionBase将字符串类型的值关联到object类型的键中, NameValueCollection多个值可以使用同一个键, Dictionary<Tkey, Tvalue>通用字典类,将键映射到值上, SortedDictionary<Tkey,Tvalue>是一个二叉树搜索树
位数组BitArray, 结构类位数组BitVector32, 在命名空间System.Collections中可以包含许多位,BitVector32是基于栈的,最多32位
枚举类
enum enumName{}
yield语句用于创建枚举器。yield return 语句返回集合的一个元素,并移动到下一个元素上,yield break语句停止迭代。这样的语句块称为迭代块
例:
//使用yield语句实现一个简单的集合
//返回类型必须为IEnumerator或IEnumerable接口,而且其中不能包含return语句
public static IEnumerable<int> GetInt()
{
int i = 0;
while(true)
{
i++;
if(i > 5)
yield break;
yield return i;
}
}
static void Main(string[] args)
{
foreach(int i in GetInt())
{
Console.WriteLine("Got" + i.ToString());
}
Console.ReadLine();
}
字符串与正则表达式
字符串处理使用StringBuilder类用于处理替换、添加和删除,System.String类,正则表达式使用System.Text.RegularExpressions
在添加额外容量时如果StringBuilder检测到容量超出,且容量没有设置新值则容量会翻倍
格式化字符串
,String.Format
使用Regex类的IsMatch()静态方法用于返回一个布尔值,说明输入是否与给定的正则表达式匹配
正则表达式中的组和捕获
GroupCollection和CaptureColle ction分别表示组合捕获集合Match类有一个方法Groups(),返回响应的GroupCollection;Group类也响应的执行一个Captures()方法,它返回CaptureCollection对象
在使用Regx.Match()方法对输入与模式进行比较时实际是按照组抽取用户信息,组的拆分方法是用@符号分开,对于单个组可以用序列?开头
结构化异常处理
try...catch...finally;
throw...语句抛出异常
其中try语句允许嵌套,可以用内层处理简单的异常,外层处理严重的异常
预定义异常,可以从从System.Exception类继承,并从程序中抛出称为预定义异常
自定义异常,常用语捕获通用异常并识别发生这种异常时的应用程序之间的关系,再把自定义异常作为特定的应用程序异常抛出,以便适当的处理
finally块是无论何时一定会执行的代码块
委托与事件
委托,类似于C++的指针函数,可用于定义回调函数,可以连接在一起方法不必与委托名完全相同,委托就是一个函数指针,不过是类型安全的
定义委托,可以在任意的位置定义委托:
public delegate void DelegateName( string message );
委托的实现在System.Delegate类中
委托的使用,例:
public delegate void MyDelegate(string message);
MyDelegate objD = new MyDelegate( AimClass.FunName );
;
--discuss with xinan
public class MyDelegate : delegate
{
PropertyInfo P1 { return "string"}
}
;
class delegate<T>
{
delegate()
{
}
delegate(T p1)
{
}
}
class Mydelegate:delegate<string>
{
Mydelegate(string p1)
{
}
}
Mydelegate myObj = funtion;
--discuss with xinan
;
objD(funParameters); //调用委托的函数
委托可以重复指定,无论是普通方法还是静态方法
多路委托,使用"+"运算符将它们分配给一个要成为多路广播委托的委托实例,组合委托可以调用组成它的那两个委托,只有相同类型的委托才可以组合,类似于字符串相加;同样委托也可以使用减运算;也就是可以将相同参数类型的方法使用一个委托进行调用。
注意:多路委托时一次调用,并可以增减,如果委托内任意方法引发了异常,而在该方法内未捕获异常该异常将传递给委托调用方,并且不在调用之后委托的方法。返回值或输出参数其值为最后调用的方法。
匿名方法和Lambda表达式
委托中使用匿名方法就不必创建单独的方法,减少了委托时需要的代码开销。在委托赋值时使用
MyDelegate objD = new delegate([parameter])
{
//代码
};
匿名方法中不能访问任何不安全的代码块,也不能访问ref,out参
数
Lambda表达式实际上就是一个匿名函数,可以包含表达式或语句
使用运算符"=>" 读作 goes to, 右边包含表达式或语句块。符号左面是参数列表,右面是语句块。同样可以使用Lambda表达式实例化委托,因为Lambda表达式本身也是匿名函数
a = j => j * j;
a = (i,j) => i * j;
委托与接口
委托和接口都允许设计器分离类型声明和实现。委托类似于C++中的函数指针,并扩展了其功能,可以进行委托方法的批量处理。
一般在开发事件模式时使用委托,当可以使用静态方法封装时使用委托效果较好。当调用方法不需要访问实现该方法的对象中的其他成员时使用委托比较好。
当存在一组可能被调用的相关方法时、当类只需要方法的单个实现时、当使用接口的类想要强制转换成其他接口或类时、当正在实现的方法链接到类的类型或标示时使用接口比较好。
事件,通常用于图形界面(GUI)中的一些操作,事件不是程序的过程流,而是建立程序之间连接的方法和运行过程的总结操作。
使用Visual Stdio IDE可以方便的添加事件处理。
事件处理时分为两类,一类是事件触发者,另一类是事件接收者
定义事件使用event关键字,事件的处理者是委托的函数。
例如:
delegate void MyDelegate();
class Program
{
public event MyDelegate FirstEvent;
static void Main( string[] args )
{
}
}
一个事件可以有多个事件接收者,这是会同步调用多个事件处理程序。可以利用线程同步线程,事件是基于EventHandler委托和Event-Args基类的。
委托与事件实例,.net Framework的事件设置准则
声明委托时 delegate使用void 作为返回类型、事件接收的两个传入参数一律命名为sender和e、定义一个为事件提供数据的类,对类以<EventName>EventArgs进行命名,从EventArgs类派生,然后添加事件的成员,如果不需要为事件提供数据类,则可以使用System.EventArgs类直接作为数据类型,这个基本类型不对事件处理程序传递任何信息。
例,下面是已火警触发为例实现事件处理:
//为事件取名,并继承自EventArgs类
public class TemperatureEventArgs: EventArgs
{
private int temperature;//其实属性方法与属性名可以不一致但不推荐
public int Temperature
{
get{ return temperature; }
}
public TemperatureEventArgs( int _temperature )
{
temperature = _temperature;
}
}
//创建事件触发类, 但并没有事件处理程序
public class EventSender
{
//定义委托, 委托为引用类型,实质为指针所以无需初始化为对象
public delegate void TemperatureEventHandler( object sender, TemperatureEventArgs e );
//定义事件对象
public event TemperatureEventHandler temperaturePress;
//定义被添加委托的函数作为事件处理函数
protected virtual void OnTemperaturePress( TemperatureEventArgs e )
{
TemperatureEventHandler handler = temperaturePress;
if( hander != null )
temperaturePress(this, e);
}
public void isTemperaturePress( int temperature)
{
OnTemperaturePress( new TemperatureEventArgs( temperature ));
}
}
//事件的处理类,或称为事件的订阅者
public class EventReceive
{
public void Press( object sender, TemperatureEventArgs e )
{
if( e.Temperature > 80 )
Console.WriteLine("马上发生火灾");
else if( e.Temperature > 50 )
Console.WriteLine("温度过高");
else
Console.WriteLine("温度正常");
}
}
//主程序中使用定义好的事件与托管
static void Main()
{
bool flag = true;
while( flag )
{
Console.WriteLine("输入检测温度");
int temperature = Convert.ToInt32( Console.ReadLine());
EventSender es = new EventSender();
EventReceive er = new EventReceive();
//添加事件发生函数的订阅函数
es.temperaturePress += new EventSender.TemperatureEventHandler( er.Press );
//事件触发就是指定的事件的属性达到某一值的时候,批量调用指定的函数集,C#中使用委托来完成这个调用的
es.isTemperaturePress( temperature );
if(temperature > 200)
{
flag = false;
}
}
//超过允许的温度200范围,程序结束
}
windows窗体,使用某一类,就需要导入对应类的命名空间,using NameSpace;
如:using System; using System.Windows.Forms;
注意是大小写敏感的
创建一个类,并继承自系统窗口类即可创建自定义的窗口类
public class myFormClass: System.Windows.Forms.Form
{
//添加默认构造函数
public myFormClass()
{
}
//[STAThread]说明该应用程序为单线程, 缩写Single Thread Application的缩写STA
[STAThread]
//定义主函数
static void Main()
{
//Application.Run() 方法用于启用标准的应用程序消息循环,有三个重载版本分别为
//不带参数、把ApplicationContext对象作为其参数、第三个版本把窗体对象作为其参数
Application.Run( new myForm());
}
}
Application对象,与当前执行的应用程序相关的信息
路径、调用其他程序、程序数据存储路径、消息循环、启动路径、消息过滤器、DoEvents操作同VB、可视化样式制定、退出与退出当前线程的消息循环
控件类,Control,派生于System.ComponentModel.Component类, Coompoenent类提供把定义的控件拖放到设计界面里,以及包含在另一个对象中的时候需要用到它
Control类定义了所有Asp.net服务器控件共享的属性、方法和事件等
控件对其中的Anchor属性,把子空间与父控件的一条边与父控件的一条边对齐并保持下去。使用AnchorStyle枚举属性
Bounds属性返回Rectangle属性,为一个控件的区域;Rectangle位于System.Draw命名空间;ClientSize是一个Size结构,大小不包含滚动条与标题栏;PointToClient和PointToScreen方法是转换结构
Windows功能, 对System.Windows.Forms.dll进行反编译就会看到一个UnsafeNativeMethods类的引用列表,.netFramework使用这个类封装所有的标准Win32 API调用
使用System.Windows.Froms命名空间可以与Win32 API进行交互, 如果需要访问Windows消息需要重写WndProc方法
Message对象是Windows消息的一个简单封装,包含HWnd、Msg、Result、LParam、WParam, 如果系统处理消息就必须把消息传递给WinProc方法、如果自己处理消息就不需要
其他控件
ToolStrip控件,用于将用户界面组合到工具栏
MenuStrip控件,轻松创建Office中那样的菜单
ContextMenuStrip,右键菜单
ToolStripContainer,用于放置漂浮的ToolStrip
ErrorProvider,用于错误验证提示
HelpProvider组件,允许挂起控件显示帮助主题
窗体Form类,继承关系Form<-ContainerControl<-Scrollable<-Control
多文档界面MDIWindowsForm,ParentForm
定制控件,从Windows窗体控件继承、从UserControl类继承、从Control类继承
处理XML,eXtensible Markup Language, 但占用空间大,不过易于跨平台传输数据
只吃w3c标准, World Wide Web Consortium, http://www.w3.org
XML1.0,包括DTD支持
XML命名空间,支持http://www.w3.org/tr/rec-xml-names-流级和DOM
XML模式, http://www.w3.org/2001/xmlSchema
xpath, http://www.w3.org/tr/xpath
xslt转换, http://www.w3.org/tr/xslt
dom level1核心、dom level2核心、soap 1.1
引用Syste.xml命名空间,提供了读写XML
xmlReader, xmlWriter, xmlTextReader快速向前读取XML数据流,xmlNodeReader对xmlNode中的数据进行快速无缓存的的访问读取,xmlReaderSetting, xmlTextWriter快速无缓存的向前写入, xmlWriterSetting;
XML的DOM处理类
xmlNode抽象类公开事件并可以绑定到数据的单个xmlNode控件,xmlAttribute一个属性,在文档类定义DTD,xmlDocument表示xml文档,xmlDataDocument允许通过相关的DataSet存储检索和操作结构化数据,xmlDocumentFragment对树插入有效地轻量对象,xmlEntity表示实体声明,xmlNotation表示方法声明,xmlLinkedNode取得紧靠该节点的节点是抽象类,xmlResolver抽象类解析外部xml资源,xmlUrlResolver统一资源定位符(URL)定义的xml文档
xml4.0、3.0、2.0可以直接在应用程序中使用,在解决方案中添加一个msxml4.dll引用即可
使用COM技术读写XML文档
C#中可以引用COM组建,项目->添加->COM->Microsoft xml v3.0/v4.0...之后才程序中添加命名空间引用using MSXML3/4.0...;
xmlPathLanguage(XPath)是一种xml记号,可以用于查询和过滤xml文档中的文本
using msxml2;
private domDocument30 doc;
private void listBox
{
doc.load("aimXmlPath");
string str = listBox.selectItem.toString();
ixmlDomNode node = doc.selectSingleNode( "BookShop/Book[@isbn="+str+"]");
messageBox.show(node.text);
}
C#使用托管来读取XML,托管代码更简洁,高效,安全。System.xml类及其子类,xmlReader, xmlWriter, System.xml.XPath, System.xml.xsl可扩展样式转换
使用System.xml.xsl命名空间;xsl可扩展样式转换xslt支持W3C XSL转换XSLT1.0推荐,可以和实现IXPathNavigable接口的存储器一起使用,在.net framework中,包含xmlDocument, xmlDataDocument和XPathDocument
使用XSLT可以将一个XML文档转换为一个简单的HTML文档,xmlCompiledTransform类
使用xsltArgumentList类,把对象和方法绑定到命名空间,可以转换过程中调用该方法
XML是把ADO.net绑定到其他空间的纽带,xml适合在应用程序和网页之间传送数据
ADO.net->xml工程使用的命名空间为:
using system.data.sqlClient;
using system.Io;
using system.xml;
ADO.net简历操作数据库的代码
public makeConnection()
{
string strConn = "data source=.;database=scout;uid=sa;pwd=abc";
SqlConnection con = new SqlConnection(strConn);
string strQuery = "select * from news";
SqlDataAdapter sda = new SqlDataAdapter(strQuery, con);
DataSet = new DataSet("XMLNews"); //使用ADO.net -> xml文档
}
实例化数据操作流MemoryStream, StreamReader, StreamWriter
MemoryStream s = new MemoryStream();
StreamReader rs = new StreamReader(s);
StreamWriter ws = new StreamWriter(s);
用于读写数据流
把XML文档转换为Ado.net数据DataSet,这样就可以把XML加载到数据库中,或者把数据绑定到DataGridView上
DataSet对象可以直接导入xml文档
objDataSet.ReadXml(strSource);
文件与注册表操作
管理文件系统, System.Io类
BinaryReader, BinaryWriter, BufferedStream, Directory静态方法类, DirectoryInfo实例方法, File静态方法类, FileInfo实例方法类, FileStream同步异步读写类, MemoryStream内存存储区, Stream字节序列一般数据流类, StreamReader一种特定编码从字节流中读取字符, StreamWriter特定编码写入, StreamWriter, StringReader, StringWriter, TextReader, TextWriter
读写文件, Sequential file包含不同长度的记录
随机文件,Random file 文件有固定的大小,通常是二进制文件
文件读写常用类
FileStream专门用于读取文件中的数据;StreamReader, StreamWriter常用于读取文件和写入文件;二进制读写BinaryReader, BinaryWriter
读取驱动器信息
可以使用DriveInfo从指定驱动器读取信息,如驱动器状态,剩余空间等
注册表信息类
Registry类,注册表首选项CurrentUser; LocalMachine; ClassesRoot; Users; PerformanceData软件的性能信息;CurrentConfig存储非用户特定的硬件信息;DynData包含动态注册表数据
读取设定数据的静态方法是 Registry.GetValue/SetValue
数据访问类
ADO.NET模型,Active data object,其命名空间中有
System.Data类,无论那种数据源,统一处理数据,其中重要的是
DataSet类;
System.Data.Common;
System.Data.OleDb;
System.Data.ProviderBase;
System.Data.Oracle;
System.Data.Sql;
System.Data.SqlClient;
System.Data.SqlTypes
在命名空间中显示的指定对象型会使得代码运行的更快。
共享类,无论处理任何数据库操作都可以使用的数据处理类
DataSet;
DataTable;
DataRow;
DataColumn;
Constraint约束;
DataRelation;
DataView;
DataColumnMapping;
DataTableMapping
数据库特定类,具有标准接口与一般类使用方法一样
Sqlcommand,
OracleCommand,
ODBCCommand,
OleDbCommand
SqlCommandBuilder,
OracleCommandBuilder,
OleDbCommandBuilder, ODBCCommandBuilder,自动生成单表命令,用于同关联的DataSet特定数据库的更改协调
SqlConnection,
OleDbConnection,
OracleConnection,
ODBCConnection
SqlDataAdapter,
OracleDataAdapter,
OleDbDataAdapter,
ODBCDataAdapter,用于生成指定的 DataSet对象
SqlParameter,
OleDbParameter,
OracleParameter,
ODBCParameter,是Command对象的参数
SqlTransaction, 指Transact-Sql事务
数据库连接字符串
字符串中的关键属性,Data Source; AttachDbFileName,若使用DataDirectory关键字赋值表示当前目录;Integrate Secuity,表示使用windows身份验证,若为fasle连接时要使用用户名密码;User Instance,判断是否使用当前用户来启动Sql server的一个实例, 为true时会将数据库附加到新的实例并新建立一个进程;User Id, Password
MSIL,反汇编程序Ildasm.exe, 推荐将关键的信息不写入代码,直接将存储于应用程序配置文件中
System.Configuration命名空间中提供用于存储配置数据的编程模型类
使用using语句块来确保释放有限的系统资源,例如保证释放SQL连接
using( SqlConnection conn = new SqlConnection(strConneciton))
{
//语句
}
无论从哪里得到资源,最好使用using语句,如果语句块内有异常发生,会自动调用对象的 IDisposable.Dispose方法,IDisposeable为接口名
命令, 由objConnection.CreateCommand()方法产生,用于执行数据库操作的select, insert, modify, delete命令
ExecuteXmlReader方法可以直接从sql server 2k以上版本返回xml流,使用时需要添加for xml子句,支持三种工作模式RAW, AUTO和EXPLICIT,返回三种不同的数据:
FOR XML RAW,返回结果集;FOR XML AUTO以层次结构的形式组织起来;FOR XML EXPLICIT唯一支持开放模式的,可以完全控制XML的查询结果
使用方法一样,只不过是返回xml的字符串集合
调用存储过程
在创建Command对象时,CommandText属性保存存储过程名,CommandType设置为CommandType.StoredProcedure;并定义SqlParameter类的对应参数数组:
//定义
SqlParameter[] arySqlParamters = { new SqlParameter("@Id", SqlDbType.Int),new SqlParameter("@Title", SqlDbType.VarChar, 200)}
//使用
arySqlParameters[0] = 2342;
使用objCommand.Parameters.AddRange(objArrrayParameters); 来添加欲调用存储过程的参数,之后调用执行命令即可
Micorosoft事务协调器MSDTC进行协调, 可以统一调度存储过程完成某一功能。
System.Transactions命名空间中的类所提供的基础结构通过支持Sql server, ado.net, msmq消息队列, 分布式协调器(MSDTC)中启动的事务,而且可以实现事务的回滚,将Command对象指定为某一事务来进行处理,例如:
try
{
objConnection.Open();
}
catch(System.Data.SqlClient.SqlException e)
{
throw new Exception( e.Message );
}
SqlTransaction myTrans = objConnection.BeginTransaction();//事务开始
try
{
objCommand.Connection = ojbConnection;
objCommand.Transaction = myTrans;
foreach( string str in strSQLs )
{
objCommand.CommandText = str;
objCommand.ExecuteNonQuery;
}
myTrans.Commit();//确认提交事物
return 0;
}
catch( System.Data.SqlClient.SqlException e )
{
myTrans.Rollback(); //事务回滚
return -1;
}
finally
{
objCommand.Dispose();//释放事务
myCn.Close();//关闭事务连接
}
数据读取器SqlDataReader,只读流,从数据库中按照指定格式读取数据,也可以进行数据转换
SqlDataReader dr = objCommand.ExecuteReader();
while( dr.Read() ) //有记录就返回true
{
string name = dr.GetString(0);
string autherEmail = dr.GetValue(1).toString; //调用数据转换方法
}
数据集,DataSet对象,ADO.net中关键的数据集合,可以进行添加删除集合
其中的DataTable对象表示要使用的数据库表,DataTable中包含DataRow, DataColumn,DataRelation数据关系,等对象集合。可以作为XML对象读写在网络上传输来实现跨平台的数据通信
数据表,DataTable,常用于DataSet中,可以使用构造函数,或DataAdapter的fill方法,或使用DataSet的ReadXml, ReadXmlSchema, InferXmlSchema方法创建
DataView类表示用于排序,筛选,搜索,编辑和导航的DataTable,可绑定数据的定义视图。它允许windows窗体和web窗体上进行数据绑定,使用DataView可以插入删除一行
objDataView.Delete(aimRow);
objDataView.AddNew();
DataTable dt = objDataView.ToTable(); //可以将DataView对象转换为DataTable对象
数据适配器DataAdapter表示一组数据命令和一个数据连接,用于在DataSet数据源之间建立连接。如果执行DataAdapter中的命令时返回多个结果集则在对应的DataSet中建立多个表,命名以TableName0-N,使用方法
SqlDataAdapter da = new SqlDAtaAdapter(objCommand);
使用fill方法可以填充DataSet, 使用update方法可以用DataSet更新数据库;单一表时可以利用CommandBuilder对象自动生成SqlDataAdapter的DeleteCommand, InsertCommand, UpdateCommand来更新DataSet;多表时只能显示设置更新语句
SqlDataAdapter da = new SqlDataAdapter( strQuery, objConnection );
da.UpdateCommand = new SqlCommand( strUpdateCommand );
SqlParameter param = da.UpdateCommand.Parameters.Add( strAdd );
param.SourceColumn = strSourceColumn;
param.SourceVersion = DataRowVersion.Original;
da.UpdateCommand.Parameters.Add( "@UpParam", SqlDbType.NChar, 20, "UpTime" );
DataSet ds = new DataSet();
从XML填充数据到DataSet中,只需调用方法objDataSet.ReadXml(strXmlSourc);
给DataSet添加数据
首先为DataSet要插入数据的DataTable创建一个行
根据需要设置DataRow
将新的对象传递给DataTable.Rows集合的Add方法
使用DataView类对DataSet排序,可以增加Filter对得到的数据进行筛选
查看.net数据,可以使用DataGridView控件来查看数据
AutoGeneraterColumns,属性指定是否由数据源创建列或手动创建;
DataMember是DataSource的子列表,指定在控件上显示的数据源中的内容,DataSource指定DataSet对象,用DataMember指定DataSet结合中的某一存储的数据集合;
objDataAdapter.Fill( objDataSet, strDataSetName );
objDataGridView.DataSource = objDataSet;
objDataGridView.DataMember = strDataSetName; //指定数据集合的索引值
可以使用List类来添加DataGridView控件
数据绑定,可以使用支持绑定的控件的DataBindings属性来设置;也可以使用添加数据源的方式进行添加数据连接;在设计器中可以指定单元格的样式;
绑定组件BindingSource,用来管理数据交互的详细信息,如将table类的对象付给绑定组件的数据源
objBindingSource.DataSource = objTable;
其中BindingSource的数据源可以是数据库的DataSet对象也可以是其他自定义对象;可以看作是一个集合进行操作
objBindingSource.Add( obj );
objDataGridView.DataSource = objBindingSource;
与Sql Server 2008交互, .net 2.0之后允许有多个运行主机,如ASP.NET, windows窗体,ie;sql server 2008允许在其进程上运行.net程序集合, 并定义了程序的运行安全许可级别safe只能访问本地数据库, external可以使用客户端的ADO.NET访问网络,文件系统及注册表, unsafe课执行任何操作
为了在sql server 2008上运行.net代码必须使用sp_configure存储过程激活:
sp_configure 'show advanced option', 1;
go
reconfigure;
go
sp_configure 'clr enable', 1;
go
reconfigure;
go
在.net 3.5中的命名空间System.Security.Permission命名空间中引入HostProtectionAttribute属性类,以便更好的保护操作系统环境
使用Microsoft.SqlServer.Server命名空间中的属性类可以使用.net framework语言创建存储过程等数据库操作
InvalidUdtException检查用户定义类型是否存在;SqlContext表示调用上下文的抽象类;SqlDataRecord表示单个数据行及其元数据;SqlFacetAttribute在T-sql语句中对用户自定义类型返回值进行评定;SqlFunctionAttribute用于将用户定义的聚合方法标记为Sql server中的函数;SqlMetaData用于从SqlDataRecord对象的参数和列指定检索元数据信息;SqlMethodAttribute指定用户定义类型的方法或属性的确定性和数据访问性质;SqlPipe允许托管存储过程,在sql server上进程内运行,一遍将结果返回调用方;sqlProcedureAttribute用于将程序集合中的方法标记为存储过程;SqlTriggerAttribute用于将程序中的方法标记为SQL Server中的触发器;SqlTriggerContext触发器上下文信息;SqlUserDefinedAggregateAttribute用户定义的聚合;SqlUserDefinedTypeAttribute用于将程序集中的类型标记为SQL server中的用户定义类型;
用户定义的合计函数,多行返回一个值,如内置合计函数有COUNT,AVG,SUM,内置合计函数只能用于内置类型;对选中的行统计需要自定义合计函数;
使用CLR编写合计函数时,必须执行一个简单类的几个方法Init()为处理的每组调用; Accumulate()为组中的的每个值调用; Merge()计算值需要与另一个合计结果合并起来时调用; Terminate()处理完每个组的最后一行后调用;
例,自定义合计函数:
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate( Format.Native )]
public struct AggSum
{
public void Init()
{
sum = 0;
}
public void Accumulate( SqlInt32 Value )
{
sum +=Value.Value;
}
public void Merge( AggSum Group )
{
sum += Group.sum
}
public SqlInt32 Terminate()
{
return new SqlInt32(sum);
}
private int sum;
}
参数类型可以自定义
使用自定义合计函数,要使用VS2008或Create Assembly语句将包含该实例的程序集加载到SqlServer中,之后可以和内部求和函数一样使用了
create assembly[AggSum](@value int) returns [int] external name [SumDemo].[AggSum]
在sql server中调用
select dbo.AggSum( parameter ) from Table
创建存储过程,CLR存储过程是指对Microsoft.net framework公共语言运行时的引用。特点:
可以有一个返回值;有输入参数;可以返回消息给客户程序;可以调用数据定义语言DLL与数据操纵语言DML
在Sql Server中创建CLR存储过程的步骤
定义存储过程为类的静态方法,并编译;使用create assembly语句在Sql server中注册程序集;通过使用create procedure语句创建引用注册程序集的存储过程
消息和调用语句依赖于System.Data.SqlClient命名空间
例:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetBookTypeCLR( int TypeId )
{
SqlConnection con = new SqlConnection("Context Connection = true");
con.Open;
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.Command.Text = "select bookId, bookName, bookAuthor, bookPrice, publisher from tblBook where typeId = @typeId order by bookId";
cmd.Parameters.Add("@typeId",SqlDbType.Int);
cmd.Parameters["@typeId"].Value = TypeId;
SqlDataReader sdr = cmd.ExecuteReader();
SqlPipe sp = SqlContext.Pipe;
sp.Send(sdr); //可以使用管道将得到的搜索结果返回到Sql用例空间
con.Close();
}
}
使用存储过程,在其他自定义函数中使用
objCommand.CommantText = strProcedureName;
objCommand.CommandType = CommandType.StoredProcedure;
SqlParameter objParamter = new SqlParameter(strParameterName, value);
cmd.Parameters.Add( objParameter );
cmd.ExecuteReader([strRunType]);
用户自定义函数,用户自定义CLR,可以创建三种类型的用户定义函数
标量值用户定义函数(返回单值)、表值用户定义函数(返回表)、用户定义聚合函数(类似于SUM,MIN)
Sql server 中创建CLR函数步骤
.net framework定义为类的静态方法,编译后生成程序集;使用create assembly语句在 sql server中注册程序集;通过create function语句创建引用注册程序集的函数。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString FunctionName([parameters])
{
//函数实现
}
}
使用自定义函数,例:select dbo.FunctionName([parameters]);
触发器,.net支持数据操纵语言DML触发器又支持数据定义语言DDL触发器。使用SqlTriggerContext的特殊类来获得INSERTD和DELETED表,确定激活了触发器的DDL操作信息。创建步骤
将触发器定义为类,定义静态函数并编译;使用create assembly注册类;创建用于已注册程序集的触发器;
例:
public partial class Trigger
{
[SqlTrigger(Name = "BookTrigger", Target = "SqlBookShoop", Event = "For insert")]
public static void BookTrigger()
{
SqlTriggerContext myTriggerContext = SqlContext.TriggerContext;
SqlPipe myPipe = SqlContext.Pipe;
SqlCommand myCommand = new SqlCommand();
//使用TriggerAction属性获取动作事件,TriggerAction.Insert/.Delete/Update
if( myTriggerContext.TriggerAction == TriggerAction.Insert )
{
myCommand.CommandText = "select * from tblBook";
}
myPipe.ExecuteAndSend( myCommand );
}
}