必备工具的安装及C#基础的介绍

【第一章工具安装和基础教学(ASP.NET编程教学)视频】

第一节必备工具的安装

1. visual studio2022安装

(1)先从网站下载安装包推荐下载VS2022社区版
下载导航
(2)下载完的程序包进行安装直到出现选择如图:

image.png

之后确定并等待安装完毕。
(3)安装完成后从开始菜单找到visual studio点击打开

image.png

image.png

(4)象征性的选择下登录或者和我一样选以后再说,选个自己喜欢的配色,后点击启动。

image.png

image.png

(5)项目名称就起名叫one好了

image.png

(6)我们点击运行看看

image.png

(7)你的效果如下说明你的第一个.net core程序帅气潇洒的创建成功了:

image.png

2. Sql server2012安装

(1)首先自行下载Sql server2012安装包,双击安装出现如下界面:

image.png

(2)点击安装,并选择全新的独立安装,选择如图:

image.png

(3)之后依次都是选择下一步操作,检测过程中可能比较慢如图:

image.png

(4)下一步,输入密钥下一步,我同意之后下一步,如图:

image.png

(5)下一步全选,安装实例默认即可,如图:

image.png

(6)一直下一步或指定sa用户密码之后添加当前用户下一步就好,如图:

image.png

(7)最后一步那就是安装了,慢慢等待安装完毕即可。如图:

image.png

第二节结构、关键字及数据类型

1. C#的简介

C#(读做 “C sharp”)。首先,说到C#,就不得不提到微软的.NET。.NET是微软推出的软件开发和运行平台,允许应用程序通过Internet进行通讯和共享数据。不管应用程序使用的是那种操作系统、设备、编程语言,对用户来讲,不管使用的是手机还是电脑,都可以愉快的使用应用程序。对软件开发者来讲,.NET平台与语言无关,我们可以使用自己熟悉的编程语言来实现快速开发,而C#是.NET平台最优秀的语言。
.NET的核心框架叫.NET Framework,是它赋予了.NET丰富而强大的功能,现在最新的.NET Farmework是4.7版本的。经过多年的发展,.NET也日趋成熟。
C#是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的面向对象的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏和模版,不允许多重继承)。C#综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。
C#的特点:
(1) 完全面向对象。
(2) 支持分布式,之所以有C#,是因为微软相信分布式应用程序是未来的趋势,即处理过程分布在客户机和服务器上。所以C#一出生就注定了能很好解决分布式问题。
(3) 跟Java类似,C#代码经过编译后,成为了一种IL(中间语言)。在运行时,再把IL编译为平台专用的代码。
(4) 健壮,C#在检查程序错误和编译与运行时错误一点也不逊于Java,C#也用了自动管理内存机制。
(5) C#不像Java那样完全摒弃了指针和手动内存管理。C#默认情况下是不能使用指针的,程序员在有必要时可以打开指针来使用。这样可以保证编程的灵活性。
(6) 安全性:C#的安全性是有.net平台来提供的。C#代码编译后成为IL语言。是一种受控代码,.net提供类型安全检查等机制保证代码是安全的。
(7) 可移植性:由于C#使用类似Java的中间语言机制。使得C#也跟Java类似,可以很方便的移植到其他系统。在运行时,再把中间代码编译为适合特定机器的代码。
(8) 解释性:C#也是一种特殊的解释性语言。
(9) 高性能:C#把代码编译成中间语言后,可以高效的执行程序。
(10)多线程:与Java类似,可以由一个主进程分出多个执行小任务的多线程。
(11) 组件模式:C#很适合组件开发。各个组件可以由其他语言实现的,然后集成在.net中。
C#是在Java流行起来后所诞生的一种新的语言。由于微软在操作系统上占有很大的优势。在以往的开发中累积了不少经验,所形成的.net平台,所以C#在Windows方面可以说比Java具有更大的优势。如果单纯从技术上来讲,C#在网络编程上可以与Java匹敌。C#还在Windows Forms也有一定的优势,同时还可以开发web服务及web应用程序等。
C#是一种非常类似于C++的语言,风格是更接近于Java,不管是C++程序员还是Java程序员,都可以很方便的转到C#上来。

2. C#的结构

一个 C# 程序主要包括以下部分:
命名空间声明(Namespace declaration)
一个 class
Class 方法
Class 属性
一个 Main 方法
语句(Statements)& 表达式(Expressions)
注释(代码中的绿色部分)
让我们看一个可以打印出 “Hello World” 的简单的代码:

  1. namespace HelloWorldApplication /*HelloWorldApplication 命名空间包含了类 HelloWorld*/
  2. {
  3. class HelloWorld /*类 HelloWorld 包含了程序使用的数据和方法声明。类一般包含多个方法。方法定义了类的行为。在这里,HelloWorld 类只有一个 Main 方法。*/
  4. {
  5. static void Main(string[] args) /* Main 方法,是所有 C# 程序的 入口点。Main 方法说明当执行时 类将做什么动作。*/
  6. {
  7. Console.WriteLine("Hello World");/* Main 方法通过语句 Console.WriteLine("Hello World"); 指定了它的行为。
  8. WriteLine 是一个定义在 System 命名空间中的 Console 类的一个方法。该语句会在屏幕上显示消息 "Hello, World!"。*/
  9. Console.ReadKey();/*最后一行 Console.ReadKey(); 是针对 VS.NET 用户的。这使得程序会等待一个按键的动作,防止程序从 Visual Studio .NET 启动时屏幕会快速运行并关闭。*/
  10. }
  11. }
  12. }

当上面的代码被编译和执行时,它会产生下列结果:

  1. Hello World

注意:
一、C# 是大小写敏感的。
二、所有的语句和表达式必须以分号(;)结尾。
三、程序的执行从 Main 方法开始。
四、与 Java 不同的是,文件名可以不同于类的名称。

3. C#的关键字

关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀。
在 C# 中,有些标识符在代码的上下文中有特殊的意义,如 get 和 set,这些被称为上下文关键字(contextual keywords)。
下表列出了 C# 中的保留关键字(Reserved Keywords)和上下文关键字(Contextual Keywords)见下表:

保留关键字
abstract as base bool break byte case
catch char checked class const continue decimal
default delegate do double else enum event
explicit extern false finally fixed float for
foreach goto if implicit in in (genericmodifier) int
interface internal is lock long namespace new
null object operator out out(genericmodifier) override params
private protected public readonly ref return sbyte
sealed short sizeof stackalloc static string struct
switch this throw true try typeof uint
ulong unchecked unsafe ushort using virtual void
volatile while
上下文关键字
add alias ascending descending dynamic from get
global group into join let orderby partial(type)
partial(method) remove select set

这些比较多大家不用刻意去记忆,在实践中积累就好。

4. C#的数据类型

白话描述:你有个变量x,看作一张纸,上面写着1,x就是值类型。还是变量x这张纸,上面画了一个路线图指向那个放1的地方,这个x就是引用类型。
值类型包括:数值类型,结构体,bool型,用户定义的结构体,枚举,可空类型。(大家简单了解就好,用到自然就懂了)
引用类型包括:数组,用户定义的类、接口、委托,object,字符串,null类型,类。(大家简单了解就好,用到自然就懂了)
值类型和引用类型区别:

值类型 引用类型
存储方式 直接存储数据本身 存储的是数据的引用,数据存储在数据堆中
内存分配 分配在栈中的 分配在堆中
效率 效率高,不需要地址转换 效率较低,需要进行地址转换
内存回收 使用完后立即回收 使用完后不立即回收,而是交给GC处理回收
赋值操作 创建一个新对象 创建一个引用
类型扩展 不易扩展,所有值类型都是密封(seal)的,所以无法派生出新的值类型 具有多态的特性方便扩展
实例分配 通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中 总是在进程堆中分配(动态分配)

装箱和拆箱(面试笔试常见题):
装箱:就是将一个值类型转换成等值的引用类型。在堆上为新生成的对象(该对象包含数据,对象本身没有名称)分配内存。
将堆栈上值类型变量的值拷贝到堆上的对象中。将堆上创建的对象的地址返回给引用类型变量(从程序员角度看,这个变量的名称就好像堆上对象的名称一样)。
拆箱:就是将一个引用类型转换成等值的值类型。将引用类型变量堆上的值拷贝到栈上面。
注:装箱和拆箱都是要消耗内存和cpu资源的,也就造成效率降低,所以要尽量避免使用。
数据类型总结:
值类型和引用类型理解透彻后,我们知道C#里面是值传递,但是有些变量是引用类型的,在传递和拷贝时需要特别注意。方法传递参数时加上ref(out),为引用传递参数。
值传递仅仅传递的是值,不影响原始值。
引用传递,传递的是内存地址,修改后会改变内存地址对应储存的值。

5. C#的数据类型转换

一、 隐式类型转换:
这些转换是 C# 默认的以安全方式进行的转换。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
int a = 10;
double b = a;//隐式转换
二、 显式类型转换:
这些转换是通过用户使用预定义的函数显式完成的。显式转换需要强制转换运算符。

  1. double c = 10.5;
  2. int d = (int)c;//显示转换

注意:(1、显式转换可能会导致错误。进行这种转换时编译器将对转换进行溢出检测。如果有溢出说明转换失败,就表明源类型不是一个合法的目标类型。无法进行类型转换。
(2、强制类型转换会造成数据丢失,如上面的例子中,最终得到的d值为10。
三、通过方法进行类型转换:
(1、使用ToString()方法。所有类型都继承了Object基类,所以都有ToString()这个方法(转化成字符串的方法)。
(2、通过int.Parse()方法转换,参数类型只支持string类型。注意:使用该方法转换时string的值不能为为NULL,不然无法通过转换;另外string类型参数也只能是各种整型,不能是浮点型,不然也无法通过转换 (例如int.Parse(“2.0”)就无法通过转换)。

  1. int i;
  2. i = int.Parse("100");

(3、通过int.TryParse()方法转换,该转换方法与int.Parse()转换方法类似,不同点在于int.Parse()方法无法转换成功的情况该方法能正常执行并返回0。也就是说int.TryParse()方法比int.Parse()方法多了一个异常处理,如果出现异常则返回false,并且将输出参数返回0。

  1. int i;
  2. string s = null;
  3. int.TryParse(s,out i);

(4、通过Convert类进行转换,Convert类中提供了很多转换的方法。使用这些方法的前提是能将需要转换的对象转换成相应的类型,如果不能转换则会报格式不对的错误。注意:使用Convert.ToInt32(double value)时,如果 value 为两个整数中间的数字,则返回二者中的偶数;即 4.5 转换为 4,而 5.5 转换为 6。
(5、实现自己的转换,通过继承接口IConventible或者TypeConventer类,从而实现自己的转换。
四、使用AS操作符转换:
使用AS操作符转换,但是AS只能用于引用类型和可为空的类型。使用as有很多好处,当无法进行类型转换时,会将对象赋值为NULL,避免类型转换时报错或是出异常。C#抛出异常在进行捕获异常并进行处理是很消耗资源的,如果只是将对象赋值为NULL的话是几乎不消耗资源的(消耗很小的资源)。
五、装箱和拆箱:
装箱和拆箱在值类型和引用类型之间架起了一座桥梁,使得任何 value-type 的值都可以转换为 object 类型的值,反过来转换也可以。
装箱和拆箱都是要消耗内存和cpu资源的,也就造成效率降低,所以要尽量避免使用。

  1. C#的变量及常量
    变量:
    所谓变量,就是在程序的运行过程中其值可以被改变的量,变量的类型可以是任何一种C#的数据类型。所有值类型的变量都是在实际存在于内存中的值,也就是说,当将一个值付给变量时执行的是值复制操作。变量的定义格式为:变量数据类型 变量名(标识符);或变量数据类型 变量名(标识符)=变量值。
类型 举例
整数类型 sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮点型 float 和 double
十进制类型 decimal
布尔类型 true 或 false 值,指定的值
空类型 可为空值的数据类型

例子:

  1. int d = 3, f = 5; /* 初始化 d 和 f. */
  2. byte z = 22; /* 初始化 z. */
  3. double pi = 3.14159; /* 声明 pi 的近似值 */
  4. char x = 'x'; /* 变量 x 的值为 'x' */

常量:
所谓常量,就是在程序的运行过程中其值不能被改变的量。常量的类型也可以是任何一种C#的数据类型。常量的定义格式为:const 常量数据类型 常量名(标识符)=常量值。
例如:

  1. const double PI=3.1415926;
  2. const string VERSION="Visual Studio 2010";

第三节运算符、判断、循环、封装及方法

1. C#的运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,分类如下:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、其他运算符。
(1) 算术运算符:假设变量 A 的值为 10,变量 B 的值为 20

运算符 描述 实例
+ 把两个操作数相加 A + B 将得到 30
- 从第一个操作数中减去第二个操作数 A - B 将得到 -10
* 把两个操作数相乘 A * B 将得到 200
/ 分子除以分母 B / A 将得到 2
% 取模运算符,整除后的余数 B % A 将得到 0
++ 自增运算符,整数值增加 1 A++ 将得到 11
自减运算符,整数值减少 1 A— 将得到 9
  1. c = a++: 先将 a 赋值给 c,再对 a 进行自增运算。
  2. c = ++a: 先将 a 进行自增运算,再将 a 赋值给 c
  3. c = a--: 先将 a 赋值给 c,再对 a 进行自减运算。
  4. c = --a: 先将 a 进行自减运算,再将 a 赋值给 c
  5. int a = 21;
  6. int b = 10;
  7. int c;
  8. c = a + b;
  9. Console.WriteLine("c 的值是 {0}", c); /*{0}是占位符*/

结果:

  1. c 的值是 31

(2) 算术运算符:假变量 A 的值为 10,变量 B 的值为 20

运算符 描述 实例
== 检查两个操作数的值是否相等,如果相等则条件为真。 (A == B) 不为真。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 (A > B) 不为真。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 (A < B) 为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 (A >= B) 不为真。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 (A <= B) 为真。
  1. int a = 21;
  2. int b = 10;
  3. if (a == b)
  4. {
  5. Console.WriteLine("a 等于 b");
  6. }
  7. else
  8. {
  9. Console.WriteLine("a 不等于 b");
  10. }

结果:

  1. a 不等于 b

(3) 逻辑运算符:假设变量A为布尔值true,变量B为布尔值 false

运算符 描述 实例
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 (A && B) 为假。
|| 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 (A || B) 为真。
! 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 !(A && B) 为真。
  1. bool a = true;
  2. bool b = true;
  3. if (a && b)
  4. {
  5. Console.WriteLine("Line 1 -条件为真");
  6. }
  7. if (a || b)
  8. {
  9. Console.WriteLine("Line 2 -条件为真");
  10. }
  11. /* 改变 a 的值 */
  12. a = false;
  13. if (a && b)
  14. {
  15. Console.WriteLine("Line 3 - 条件为真");
  16. }
  17. else
  18. {
  19. Console.WriteLine("Line 3 - 条件不为真");
  20. }

结果:

  1. Line 1 - 条件为真
  2. Line 2 - 条件为真
  3. Line 3 - 条件不为真

(4) 位运算符:(关联了二进制等了解即可,一般用于加解密)

p q p & q p|q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:

  1. A = 0011 1100
  2. B = 0000 1101
  3. -----------------
  4. A&B = 0000 1100
  5. A|B = 0011 1101
  6. A^B = 0011 0001
  7. ~A = 1100 0011

假设变量 A 的值为 60,变量 B 的值为 13

运算符 描述 实例
& 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。 (A & B) 将得到 12,即为 0000 1100
| 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。 (A | B) 将得到 61,即为 0011 1101
^ 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。 (A ^ B) 将得到 49,即为 0011 0001
~ 按位取反运算符是一元运算符,具有”翻转”位效果,即0变成1,1变成0,包括符号位。 (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 A << 2 将得到 240,即为 1111 0000
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 A >> 2 将得到 15,即为 0000 1111
  1. int a = 60; /* 60 = 0011 1100 */
  2. int b = 13; /* 13 = 0000 1101 */
  3. int c = 0;
  4. c = a & b; /* 12 = 0000 1100 */
  5. Console.WriteLine("c 的值是 {0}", c );

结果:

  1. c 的值是 12

(5) 赋值运算符:

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 C
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C = A 相当于 C = C A
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&= 按位与且赋值运算符 C &= 2 等同于 C = C & 2
^= 按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2
|= 按位或且赋值运算符 C |= 2 等同于 C = C | 2
  1. int a = 21;
  2. int c;
  3. c = a;
  4. Console.WriteLine("c 的值 = {0}", c);

结果:

  1. c 的值 = 21

(6) 其他运算符: 其他一些重要的运算符,包括 sizeof、typeof 和 ? :。

运算符 描述 实例
sizeof() 返回数据类型的大小。 sizeof(int),将返回 4.
typeof() 返回 class 的类型。 typeof(StreamReader);
& 返回变量的地址。 &a; 将得到变量的实际地址。
* 变量的指针。 *a; 将指向一个变量。
? : 条件表达式 如果条件为真 ? 则为 X : 否则为 Y
is 判断对象是否为某一类型。 If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。
as 强制转换,即使转换失败也不会抛出异常。 Object obj = new StringReader(“Hello”);
  1. StringReader r = obj as StringReader;
  2. /* sizeof 运算符的实例 */
  3. Console.WriteLine("int 的大小是 {0}", sizeof(int));
  4. Console.WriteLine("short 的大小是 {0}", sizeof(short));
  5. Console.WriteLine("double 的大小是 {0}", sizeof(double));
  6. /* 三元运算符的实例 */
  7. int a, b;
  8. a = 10;
  9. b = (a == 1) ? 20 : 30;
  10. Console.WriteLine("b 的值是 {0}", b);
  11. b = (a == 10) ? 20 : 30;
  12. Console.WriteLine("b 的值是 {0}", b);

结果:

  1. int 的大小是 4
  2. short 的大小是 2
  3. double 的大小是 8
  4. b 的值是 30
  5. b 的值是 20

(7) 运算符优先级: 运算符的优先级确定表达式中项的组合。这
会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。

类别 运算符 结合性
后缀 () [] -> . ++ - - 从左到右
一元 + - ! ~ ++ - - (type)* & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 << >> 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR 从左到右
逻辑与 AND && 从左到右
逻辑或 OR 从左到右
条件 ?: 从右到左
赋值 = += -= *= /= %=>>= <<= &= ^= = 从右到左
逗号 , 从左到右
2. C#的判断

C# 提供了以下类型的判断语句:

语句 描述
if 语句 一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。
if…else 语句 一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。
嵌套 if 语句 您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。
switch 语句 一个 switch 语句允许测试一个变量等于多个值时的情况。
嵌套 switch 语句 您可以在一个 switch 语句内使用另一个 switch 语句。
  1. /* 局部变量定义 */
  2. int a = 100;
  3. /* 检查布尔条件 */
  4. if (a < 20)
  5. {
  6. /* 如果条件为真,则输出下面的语句 */
  7. Console.WriteLine("a 小于 20");
  8. }
  9. else
  10. {
  11. /* 如果条件为假,则输出下面的语句 */
  12. Console.WriteLine("a 大于 20");
  13. }
  14. Console.WriteLine("a 的值是 {0}", a);
  15. 结果:
  16. a 大于 20
  17. a 的值是 100
  18. /* 局部变量定义 */
  19. char grade = 'B';
  20. switch (grade)
  21. {
  22. case 'A':
  23. Console.WriteLine("很棒!");
  24. break;
  25. case 'B':
  26. case 'C':
  27. Console.WriteLine("做得好");
  28. break;
  29. case 'D':
  30. Console.WriteLine("您通过了");
  31. break;
  32. case 'F':
  33. Console.WriteLine("最好再试一下");
  34. break;
  35. default:
  36. Console.WriteLine("无效的成绩");
  37. break;
  38. }
  39. Console.WriteLine("您的成绩是 {0}", grade);

结果:

  1. 做得好
  2. 您的成绩是 B
3. C#的循环

C# 提供了以下几种循环类型:
循环类型 描述
while 循环 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。
for/foreach 循环 多次执行一个语句序列,简化管理循环变量的代码。
do…while 循环 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。
嵌套循环 您可以在 while、for 或 do..while 循环内使用一个或多个循环。

  1. /* 局部变量定义 */
  2. int a = 10;
  3. /* while 循环执行 */
  4. while (a < 20)
  5. {
  6. Console.WriteLine("a 的值: {0}", a);
  7. a++;
  8. }
  9. /*for循环执行 */
  10. for (int a = 10; a < 20; a = a + 1)
  11. {
  12. Console.WriteLine("a 的值: {0}", a);
  13. }
  14. /* do 循环执行 */
  15. do
  16. {
  17. Console.WriteLine("a 的值: {0}", a);
  18. a = a + 1;
  19. } while (a < 20);

结果均为:

  1. a 的值: 10
  2. a 的值: 11
  3. a 的值: 12
  4. a 的值: 13
  5. a 的值: 14
  6. a 的值: 15
  7. a 的值: 16
  8. a 的值: 17
  9. a 的值: 18
  10. a 的值: 19
  1. int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
  2. foreach (int element in fibarray)
  3. {
  4. System.Console.WriteLine(element);
  5. }

结果:

  1. 0
  2. 1
  3. 1
  4. 2
  5. 3
  6. 5
  7. 8
  8. 13
4. C#的封装

定义:”把一个或多个项目封闭在一个物理的或者逻辑的包中”。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。
抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化,封装则使开发者实现所需级别的抽象。
C#封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符来实现。
一个 访问修饰符定义了一个类成员的范围和可见性。C#支持的访问修饰符如下所示:
public:所有对象都可以访问;
private:对象本身在对象内部可以访问;
protected:只有该类对象及其子类对象可以访问;
internal:同一个程序集的对象可以访问;
protected internal:访问限于当前程序集或派生自包含类的类型。
比如说:一个人A为父类,他的儿子B,妻子C,私生子D(注:D不在他家里)
如果我们给A的事情
增加修饰符:
public事件,地球人都知道,全公开
protected事件,A,B,D知道(A和他的所有儿子知道,妻子C不知道)
private事件,只有A知道(隐私?心事?)
internal事件,A,B,C知道(A家里人都知道,私生子D不知道)
protected internal事件,A,B,C,D都知道,其它人不知道

5. C#的方法

一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块,方法也可以称为函数。每一个 C# 程序至少有一个带有 Main 方法的类。
要使用一个方法,您需要:定义方法及调用方法。

  1. public int FindMax(int num1, int num2)
  2. {
  3. /* 局部变量声明 */
  4. int result;
  5. if (num1 > num2)
  6. result = num1;
  7. else
  8. result = num2;
  9. return result;
  10. }
  11. static void Main(string[] args)
  12. {
  13. /* 局部变量定义 */
  14. int a = 100;
  15. int b = 200;
  16. int ret;
  17. FindMax(a, b);
  18. Console.WriteLine("最大值是: {0}", ret );
  19. }

结果:

  1. 最大值是: 200
6. C#的可空类型(Nullable)

(1)、C# 提供了一个特殊的数据类型,nullable 类型(可空类型)
可空类型可以表示其基础值类型正常范围内的值,再加上一个
null值。

  1. int? num1 = null;

(2)、Null 合并运算符( ?? )
Null 合并运算符用于定义可空类型和引用类型的默认值。Null 合并运算符为类型转换定义了一个预设值,以防可空类型的值为 Null。Null 合并运算符把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型。如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。

  1. double? num1 = null;
  2. double? num2 = 3.14157;
  3. double num3;
  4. num3 = num1 ?? 5.34;
  5. Console.WriteLine("num3 的值: {0}", num3);
  6. num3 = num2 ?? 5.34;
  7. Console.WriteLine("num3 的值: {0}", num3);

结果:

  1. num3 的值: 5.34
  2. num3 的值: 3.14157

第四节数组、字符串、枚举和类

1. C#的数组(Array)

数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
声明数组变量并不是声明 number0、number1、…、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。这里我就只简单介绍一维数组,大家想往深里面学请移步百度。
(1) 初始化数组

  1. double[] balance = new double[10];

给数组赋值:

  1. double[] balance = new double[10];
  2. balance[0] = 4500.0;

创建并初始化数组:

  1. int [] marks = new int[5] { 99, 98, 92, 97, 95};
  2. int [] marks = new int[] { 99, 98, 92, 97, 95};

数组赋值:

  1. int [] marks = new int[] { 99, 98, 92, 97, 95};
  2. int[] score = marks;

(2) 使用

  1. int [] n = new int[10];
  2. /* n 是一个带有 10 个整数的数组 */
  3. /* 初始化数组 n 中的元素 */
  4. for ( int i = 0; i < 10; i++ )
  5. {
  6. n[i] = i + 100;
  7. }
  8. /* 输出每个数组元素的值 */
  9. foreach (int j in n )
  10. {
  11. int i = j-100;
  12. Console.WriteLine("Element[{0}] = {1}", i, j);
  13. }
  14. Console.ReadKey();

结果:

  1. Element[0] = 100
  2. Element[1] = 101
  3. Element[2] = 102
  4. Element[3] = 103
  5. Element[4] = 104
  6. Element[5] = 105
  7. Element[6] = 106
  8. Element[7] = 107
  9. Element[8] = 108
  10. Element[9] = 109
2. C#的字符串(String)

可以使用字符数组来表示字符串,但是,更常见的做法是使用string关键字来声明一个字符串变量。string关键字是 System.String类的别名。
(1) 创建String对象
您可以使用以下方法之一来创建 string 对象:
(1通过给 String 变量指定一个字符串

  1. string fname, lname;
  2. fname = "Chang";
  3. lname = "Icd卡";

(2通过使用 String 类构造函数

  1. char[] letters = { 'H', 'e', 'l', 'l','o' };
  2. string greetings = new string(letters);
  3. Console.WriteLine("Greetings: {0}", greetings);

(3通过使用字符串串联运算符( + )

  1. string fullname = fname + lname;
  2. Console.WriteLine("Full Name: {0}", fullname);

(4通过检索属性或调用一个返回字符串的方法

  1. string[] sarray = { "Hello", "From", "Tutorials", "Point" };
  2. string message = String.Join(" ", sarray);
  3. Console.WriteLine("Message: {0}", message);

(5通过格式化方法来转换一个值或对象为它的字符串表示形式

  1. DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1);
  2. string chat = String.Format("Message sent at {0:t} on {0:D}", waiting);
  3. Console.WriteLine("Message: {0}", chat);

(2) String类的属性

序号 属性名称 & 描述
1 Chars在当前 String 对象中获取 Char 对象的指定位置。
2 Length在当前的 String 对象中获取字符数。

(3) String类的方法

序号 方法名称 & 描述
1 public static int Compare( string strA, string strB ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。该方法区分大小写。
2 public static int Compare( string strA, string strB, bool ignoreCase ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。但是,如果布尔参数为真时,该方法不区分大小写。
3 public static string Concat( string str0, string str1 ) 连接两个 string 对象。
4 public static string Concat( string str0, string str1, string str2 ) 连接三个 string 对象。
5 public static string Concat( string str0, string str1, string str2, string str3 ) 连接四个 string 对象。
6 public bool Contains( string value ) 返回一个表示指定 string 对象是否出现在字符串中的值。
7 public static string Copy( string str ) 创建一个与指定字符串具有相同值的新的 String 对象。
8 public void CopyTo( int sourceIndex, char[] destination, int destinationIndex, int count ) 从 string 对象的指定位置开始复制指定数量的字符到 Unicode 字符数组中的指定位置。
9 public bool EndsWith( string value ) 判断 string 对象的结尾是否匹配指定的字符串。
10 public bool Equals( string value ) 判断当前的 string 对象是否与指定的 string 对象具有相同的值。
11 public static bool Equals( string a, string b ) 判断两个指定的 string 对象是否具有相同的值。
12 public static string Format( string format, Object arg0 ) 把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。
13 public int IndexOf( char value ) 返回指定 Unicode 字符在当前字符串中第一次出现的索引,索引从 0 开始。
14 public int IndexOf( string value ) 返回指定字符串在该实例中第一次出现的索引,索引从 0 开始。
15 public int IndexOf( char value, int startIndex ) 返回指定 Unicode 字符从该字符串中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
16 public int IndexOf( string value, int startIndex ) 返回指定字符串从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
17 public int IndexOfAny( char[] anyOf ) 返回某一个指定的 Unicode 字符数组中任意字符在该实例中第一次出现的索引,索引从 0 开始。
18 public int IndexOfAny( char[] anyOf, int startIndex ) 返回某一个指定的 Unicode 字符数组中任意字符从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
19 public string Insert( int startIndex, string value ) 返回一个新的字符串,其中,指定的字符串被插入在当前 string 对象的指定索引位置。
20 public static bool IsNullOrEmpty( string value ) 指示指定的字符串是否为 null 或者是否为一个空的字符串。
21 public static string Join( string separator, string[] value ) 连接一个字符串数组中的所有元素,使用指定的分隔符分隔每个元素。
22 public static string Join( string separator, string[] value, int startIndex, int count ) 连接接一个字符串数组中的指定位置开始的指定元素,使用指定的分隔符分隔每个元素。
23 public int LastIndexOf( char value ) 返回指定 Unicode 字符在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
24 public int LastIndexOf( string value ) 返回指定字符串在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
25 public string Remove( int startIndex ) 移除当前实例中的所有字符,从指定位置开始,一直到最后一个位置为止,并返回字符串。
26 public string Remove( int startIndex, int count ) 从当前字符串的指定位置开始移除指定数量的字符,并返回字符串。
27 public string Replace( char oldChar, char newChar ) 把当前 string 对象中,所有指定的 Unicode 字符替换为另一个指定的 Unicode 字符,并返回新的字符串。
28 public string Replace( string oldValue, string newValue ) 把当前 string 对象中,所有指定的字符串替换为另一个指定的字符串,并返回新的字符串。
29 public string[] Split( params char[] separator ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。
30 public string[] Split( char[] separator, int count ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。int 参数指定要返回的子字符串的最大数目。
31 public bool StartsWith( string value ) 判断字符串实例的开头是否匹配指定的字符串。
32 public char[] ToCharArray()返回一个带有当前 string 对象中所有字符的 Unicode 字符数组。
33 public char[] ToCharArray( int startIndex, int length ) 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组,从指定的索引开始,直到指定的长度为止。
34 public string ToLower()把字符串转换为小写并返回。
35 public string ToUpper()把字符串转换为大写并返回。
36 public string Trim()移除当前 String 对象中的所有前导空白字符和后置空白字符。

注:我这里仅列举了常用的,请访问 MSDN 库,查看完整的方法列表和 String 类构造函数。

3. C#的结构体(Struct)

结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。我们使用struct 关键字用于创建结构体。
(1) 定义结构体并使用

  1. struct Books /* 定义books结构体*/
  2. {
  3. public string title;
  4. public string author;
  5. public string subject;
  6. public int book_id;
  7. };
  8. public class testStructure
  9. {
  10. public static void Main(string[] args)
  11. {
  12. Books Book1; /* 声明 Book1,类型为 Book */
  13. Books Book2; /* 声明 Book2,类型为 Book */
  14. /* book 1 详述 */
  15. Book1.title = "C Programming";
  16. Book1.author = "Nuha Ali";
  17. Book1.subject = "C Programming Tutorial";
  18. Book1.book_id = 6495407;
  19. /* book 2 详述 */
  20. Book2.title = "Telecom Billing";
  21. Book2.author = "Zara Ali";
  22. Book2.subject = "Telecom Billing Tutorial";
  23. Book2.book_id = 6495700;
  24. /* 打印 Book1 信息 */
  25. Console.WriteLine( "Book 1 title : {0}", Book1.title);
  26. Console.WriteLine("Book 1 author : {0}", Book1.author);
  27. Console.WriteLine("Book 1 subject : {0}", Book1.subject);
  28. Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);
  29. /* 打印 Book2 信息 */
  30. Console.WriteLine("Book 2 title : {0}", Book2.title);
  31. Console.WriteLine("Book 2 author : {0}", Book2.author);
  32. Console.WriteLine("Book 2 subject : {0}", Book2.subject);
  33. Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);
  34. Console.ReadKey();
  35. }
  36. }

结果:

  1. Book 1 title : C Programming
  2. Book 1 author : Nuha Ali
  3. Book 1 subject : C Programming Tutorial
  4. Book 1 book_id : 6495407
  5. Book 2 title : Telecom Billing
  6. Book 2 author : Zara Ali
  7. Book 2 subject : Telecom Billing Tutorial
  8. Book 2 book_id : 6495700

(2) C#结构体的特点
(1结构可带有方法、字段、索引、属性、运算符方法和事件。
(2结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义默认的构造函数。默认的构造函数是自动定义的,且不能被改变。
(3与类不同,结构不能继承其他的结构或类。
(4结构不能作为其他结构或类的基础结构。
(5结构可实现一个或多个接口。
(6结构成员不能指定为 abstract、virtual 或 protected。
(7当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
(8如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
(3) C#结构体和类的不同点
(1类是引用类型,结构是值类型。
(2结构不支持继承。
(3结构不能声明默认的构造函数。

4. C#的枚举(Enum)

枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。

  1. enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };//默认同下
  2. enum Days {
  3. Sun=0, Mon=1, tue=2, Wed=3, thu=4, Fri=5, Sat=6
  4. };//设置值
  5. static void Main(string[] args)
  6. {
  7. int WeekdayStart = (int)Days.Mon;
  8. int WeekdayEnd = (int)Days.Fri;
  9. Console.WriteLine("Monday: {0}", WeekdayStart);
  10. Console.WriteLine("Friday: {0}", WeekdayEnd);
  11. Console.ReadKey();
  12. }

结果:

  1. Monday: 1
  2. Friday: 5
  3. `
5. C#的类(Class)

当你定义一个类时,你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据,但它定义了类的名称意味着什么,也就是说,类的对象由什么组成及在这个对象上可执行什么操作。对象是类的实例。构成类的方法和变量成为类的成员。
(1) 类的定义
类的定义是以关键字 class 开始,后跟类的名称。类的主体,包含在一对花括号内。
(2) 成员函数和封装
类的成员函数是一个在类定义中有它的定义或原型的函数,就像其他变量一样。作为类的一个成员,它能在类的任何对象上操作,且能访问该对象的类的所有成员。
成员变量是对象的属性(从设计角度),且它们保持私有来实现封装。这些变量只能使用公共成员函数来访问。
(3) 构造函数
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
构造函数的名称与类的名称完全相同,它没有任何返回类型。

  1. class Line
  2. {
  3. private double length; // 线条的长度
  4. public Line()
  5. {
  6. Console.WriteLine("对象已创建");
  7. }
  8. public Line(double len) // 参数化构造函数
  9. {
  10. Console.WriteLine("对象已创建,length = {0}", len);
  11. length = len;
  12. }
  13. }

(4) 析构函数
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。在C#中不建议使用析构函数,析构函数作为保留的语法为兼容C++而设立的。

  1. public Line() // 构造函数
  2. {
  3. Console.WriteLine("对象已创建");
  4. }
  5. ~Line() //析构函数
  6. {
  7. Console.WriteLine("对象已删除");
  8. }

(5) 类的静态成员
我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。
关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取。静态变量可在成员函数或类的定义外部进行初始化。你也可以在类的定义内部初始化静态变量。

  1. class StaticVar
  2. {
  3. public static int num=0;
  4. public void count()
  5. {
  6. num++;
  7. }
  8. public int getNum()
  9. {
  10. return num;
  11. }
  12. }
  13. class StaticTester
  14. {
  15. static void Main(string[] args)
  16. {
  17. StaticVar s1 = new StaticVar();
  18. StaticVar s2 = new StaticVar();
  19. s1.count();
  20. s2.count();
  21. Console.WriteLine("s1 的变量 num: {0}", s1.getNum());
  22. Console.WriteLine("s2 的变量 num: {0}", s2.getNum());
  23. Console.ReadKey();
  24. }
  25. }

结果:

  1. s1 的变量 num 2
  2. s2 的变量 num 2

你也可以把一个成员函数声明为 static。这样的函数只能访问静态变量。静态函数在对象被创建之前就已经存在了,不需要创建对象。
例如:

  1. Console.WriteLine("变量 num: {0}", StaticVar.getNum());

第五节ASP.NET面向对象三大特性

1. C#的封装

封装被定义为”把一个或多个项目封闭在一个物理的或者逻辑的包中”。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。第三节课,基础介绍2的第四块对封装进行了深入的介绍,详情请异步第一章第三节课的第四块。

2. C#的继承

继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。
继承的思想实现了 属于(IS-A) 关系。例如,哺乳动物 属于(IS-A) 动物,狗 属于(IS-A) 哺乳动物,因此狗 属于(IS-A) 动物。
(1) 基类和派生类
一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。

  1. using System;
  2. namespace BaseClassWithSubClass
  3. {
  4. class SetHeightAndWidth {//基类
  5. protected int height;
  6. protected int width;
  7. public void SetWidth(int w)
  8. {
  9. width = w;
  10. }
  11. public void SetHeight(int h)
  12. {
  13. height = h;
  14. }
  15. }
  16. class Area : SetHeightAndWidth {//派生类
  17. public int GetArea() {
  18. return (height*width);
  19. }
  20. }
  21. class Program
  22. {
  23. static void Main(string[] args)
  24. {
  25. Area area = new Area();
  26. area.SetWidth(20);
  27. area.SetHeight(10);
  28. Console.WriteLine("总面积: {0}", area.GetArea());
  29. Console.ReadKey();
  30. }
  31. }
  32. }

结果:

  1. 总面积:200

(2) 基类的初始化
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。您可以在成员初始化列表中进行父类的初始化。

  1. using System;
  2. namespace BaseInitialize
  3. {
  4. class Rectangle
  5. {
  6. // 成员变量
  7. protected double length;
  8. protected double width;
  9. public Rectangle(double l, double w)
  10. {
  11. length = l;
  12. width = w;
  13. }
  14. public double GetArea()
  15. {
  16. return length * width;
  17. }
  18. public void Display()
  19. {
  20. Console.WriteLine("长度: {0}", length);
  21. Console.WriteLine("宽度: {0}", width);
  22. Console.WriteLine("面积: {0}", GetArea());
  23. }
  24. }//end class Rectangle
  25. class Tabletop : Rectangle
  26. {
  27. public Tabletop(double l, double w) : base(l, w)
  28. { }
  29. public double GetCost()
  30. {
  31. double cost;
  32. cost = GetArea() * 70;
  33. return cost;
  34. }
  35. public new void Display()
  36. {
  37. base.Display();
  38. Console.WriteLine("成本: {0}", GetCost());
  39. }
  40. }
  41. class Program
  42. {
  43. static void Main(string[] args)
  44. {
  45. Tabletop t = new Tabletop(4.5, 7.5);
  46. t.Display();
  47. Console.ReadLine();
  48. Console.ReadKey();
  49. }
  50. }
  51. }

结果:

  1. 长度: 4.5
  2. 宽度: 7.5
  3. 面积: 33.75
  4. 成本: 2362.5

(3) C#的多重继承
多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。C# 不支持多重继承。但是,您可以使用接口来实现多重继承。

  1. using System;
  2. namespace MoreBaseClass
  3. {
  4. class Program
  5. {
  6. class SetHeightAndWidth
  7. {//基类
  8. protected int height;
  9. protected int width;
  10. public void SetWidth(int w)
  11. {
  12. width = w;
  13. }
  14. public void SetHeight(int h)
  15. {
  16. height = h;
  17. }
  18. }
  19. // 接口 PaintCost
  20. public interface ICost
  21. {
  22. int GetCost(int area);
  23. }
  24. class Area : SetHeightAndWidth, ICost
  25. {//派生类
  26. public int GetArea()
  27. {
  28. return (height * width);
  29. }
  30. public int GetCost(int area)//两万一平
  31. {
  32. return area * 20000;
  33. }
  34. }
  35. static void Main(string[] args)
  36. {
  37. Area area = new Area();
  38. area.SetWidth(20);
  39. area.SetHeight(40);
  40. int getArea = area.GetArea();
  41. Console.WriteLine("房子总面积: {0}平方米", getArea);
  42. Console.WriteLine("房子购买消费了: {0}元人民币", area.GetCost(getArea));
  43. Console.ReadKey();
  44. }
  45. }
  46. }

房子总面积: 800平方米
房子购买消费了: 16000000元人民币

3. C#的多态

多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为”一个接口,多个功能”。
多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
(1) 静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了函数重载和运算符重载两种技术来实现静态多态性。
(1函数重载(Overload):您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。

  1. using System;
  2. namespace MothedOvApplication
  3. {
  4. class Program
  5. {
  6. void print(int i)
  7. {
  8. Console.WriteLine("Printing int: {0}", i);
  9. }
  10. void print(double f)
  11. {
  12. Console.WriteLine("Printing float: {0}", f);
  13. }
  14. void print(string s)
  15. {
  16. Console.WriteLine("Printing string: {0}", s);
  17. }
  18. static void Main(string[] args)
  19. {
  20. Program p = new Program();
  21. // 调用 print 来打印整数
  22. p.print(5);
  23. // 调用 print 来打印浮点数
  24. p.print(500.263);
  25. // 调用 print 来打印字符串
  26. p.print("Hello C#");
  27. Console.ReadKey();
  28. }
  29. }
  30. }

结果:

  1. Printing int: 5
  2. Printing float: 500.263
  3. Printing string: Hello C#

(2运算符重载:您可以重定义或重载 C# 中内置的运算符。因此,我们也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
可重载与不可重载的运算符:

运算符 描述
+, -, !, ~, ++, — 这些一元运算符只有一个操作数,且可以被重载。
+, -, *, /, % 这些二元运算符带有两个操作数,且可以被重载。
==, !=, <, >, <=, >= 这些比较运算符可以被重载。
&&, 这些条件逻辑运算符不能被直接重载。
+=, -=, *=, /=, %= 这些赋值运算符不能被重载。
=, ., ?:, ->, new, is, sizeof, typeof 这些运算符不能被重载。
  1. using System;
  2. namespace OperatorOv
  3. {
  4. class Box
  5. {
  6. private double length; // 长度
  7. private double breadth; // 宽度
  8. private double height; // 高度
  9. public double getVolume()
  10. {
  11. return length * breadth * height;
  12. }
  13. public void setLength(double len)
  14. {
  15. length = len;
  16. }
  17. public void setBreadth(double bre)
  18. {
  19. breadth = bre;
  20. }
  21. public void setHeight(double hei)
  22. {
  23. height = hei;
  24. }
  25. // 重载 + 运算符来把两个 Box 对象相加
  26. public static Box operator +(Box b, Box c)
  27. {
  28. Box box = new Box();
  29. box.length = b.length + c.length;
  30. box.breadth = b.breadth + c.breadth;
  31. box.height = b.height + c.height;
  32. return box;
  33. }
  34. }
  35. class Program
  36. {
  37. static void Main(string[] args)
  38. {
  39. Box Box1 = new Box(); // 声明 Box1,类型为 Box
  40. Box Box2 = new Box(); // 声明 Box2,类型为 Box
  41. Box Box3 = new Box(); // 声明 Box3,类型为 Box
  42. double volume = 0.0; // 体积
  43. // Box1 详述
  44. Box1.setLength(6.0);
  45. Box1.setBreadth(7.0);
  46. Box1.setHeight(5.0);
  47. // Box2 详述
  48. Box2.setLength(12.0);
  49. Box2.setBreadth(13.0);
  50. Box2.setHeight(10.0);
  51. // Box1 的体积
  52. volume = Box1.getVolume();
  53. Console.WriteLine("Box1 的体积: {0}", volume);
  54. // Box2 的体积
  55. volume = Box2.getVolume();
  56. Console.WriteLine("Box2 的体积: {0}", volume);
  57. // 把两个对象相加
  58. Box3 = Box1 + Box2;
  59. // Box3 的体积
  60. volume = Box3.getVolume();
  61. Console.WriteLine("Box3 的体积: {0}", volume);
  62. Console.ReadKey();
  63. }
  64. }
  65. }

结果:

  1. Box1 的体积: 210
  2. Box2 的体积: 1560
  3. Box3 的体积: 5400

(2) 动态多态性
C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。
请注意,下面是有关抽象类的一些规则:
您不能创建一个抽象类的实例。
您不能在一个抽象类外部声明一个抽象方法。
通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。

  1. using System;
  2. namespace MothedOvApplication
  3. {
  4. abstract class Shape
  5. {
  6. public abstract int area();
  7. }
  8. class Rectangle : Shape
  9. {
  10. private int length;
  11. private int width;
  12. public Rectangle(int a = 0, int b = 0)
  13. {
  14. length = a;
  15. width = b;
  16. }
  17. public override int area()
  18. {
  19. Console.WriteLine("Rectangle 类的面积:");
  20. return (width * length);
  21. }
  22. }
  23. class Program
  24. {
  25. static void Main(string[] args)
  26. {
  27. Rectangle r = new Rectangle(10, 10);
  28. double a = r.area();
  29. Console.WriteLine("面积: {0}", a);
  30. Console.ReadKey();
  31. }
  32. }
  33. }

结果:

  1. Rectangle 类的面积:
  2. 面积: 100

当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。

  1. using System;
  2. namespace MothedOvApplication
  3. {
  4. class Shape
  5. {
  6. protected int width, height;
  7. public Shape(int a = 0, int b = 0)
  8. {
  9. width = a;
  10. height = b;
  11. }
  12. public virtual int area()
  13. {
  14. Console.WriteLine("父类的面积:");
  15. return 0;
  16. }
  17. }
  18. class Rectangle : Shape
  19. {
  20. public Rectangle(int a = 0, int b = 0)
  21. : base(a, b)
  22. {
  23. }
  24. public override int area()//重写
  25. {
  26. Console.WriteLine("Rectangle 类的面积:");
  27. return (width * height);
  28. }
  29. }
  30. class Triangle : Shape
  31. {
  32. public Triangle(int a = 0, int b = 0)
  33. : base(a, b)
  34. {
  35. }
  36. public override int area()
  37. {
  38. Console.WriteLine("Triangle 类的面积:");
  39. return (width * height / 2);
  40. }
  41. }
  42. class Caller
  43. {
  44. public void CallArea(Shape sh)
  45. {
  46. int a;
  47. a = sh.area();
  48. Console.WriteLine("面积: {0}", a);
  49. }
  50. }
  51. class Program
  52. {
  53. static void Main(string[] args)
  54. {
  55. Caller c = new Caller();
  56. Rectangle r = new Rectangle(10, 7);
  57. Triangle t = new Triangle(10, 5);
  58. c.CallArea(r);
  59. c.CallArea(t);
  60. Console.ReadKey();
  61. }
  62. }
  63. }

结果:

  1. Rectangle 类的面积:
  2. 面积:70
  3. Triangle 类的面积:
  4. 面积:25

第六节接口、集合、异常处理

1. 接口

接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。
接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。
接口使得实现接口的类或结构在形式上保持一致。
抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。
(1) 接口定义

  1. using System;
  2. namespace MyInterface
  3. {
  4. interface IMyInterface
  5. {
  6. // 接口成员
  7. void MethodToImplement();
  8. }
  9. class Program:IMyInterface
  10. {
  11. static void Main(string[] args)
  12. {
  13. Program p = new Program();
  14. p.MethodToImplement();
  15. Console.ReadKey();
  16. }
  17. //继承接口后,我们需要实现接口的方法 MethodToImplement() , 方法名必须与接口定义的方法名一致。
  18. public void MethodToImplement() {
  19. Console.WriteLine("This is My Interface!");
  20. }
  21. }
  22. }

结果:

  1. This is My Interface!

(2) 接口继承
定义了两个接口 IMyInterface 和 IParentInterface。
如果一个接口继承其他接口,那么实现类或结构就需要实现所有接口的成员。
以下实例 IMyInterface 继承了 IParentInterface 接口,因此接口实现类必须实现 MethodToImplement() 和 ParentInterfaceMethod() 方法:

  1. using System;
  2. namespace MyInterface
  3. {
  4. interface IParentInterface
  5. {
  6. void ParentInterfaceMethod();
  7. }
  8. interface IMyInterface : IParentInterface
  9. {
  10. void MethodToImplement();
  11. }
  12. class Program:IMyInterface
  13. {
  14. static void Main(string[] args)
  15. {
  16. Program p = new Program();
  17. p.MethodToImplement();
  18. p.ParentInterfaceMethod();
  19. }
  20. public void MethodToImplement()//继承接口后,我们需要实现接口的方法名必须与接口定义的方法名一致。
  21. {
  22. Console.WriteLine("This is My Interface!");
  23. }
  24. public void ParentInterfaceMethod()
  25. {
  26. Console.WriteLine("This is My Interface2!");
  27. }
  28. }
  29. }

结果:

  1. This is My Interface!
  2. This is My Interface2!
2. 集合

集合(Collection)类是专门用于数据存储和检索的类。这些类提供了对栈(stack)、队列(queue)、列表(list)和哈希表(hash table)的支持。大多数集合类实现了相同的接口。集合(Collection)类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等。这些类创建 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。
(1) 动态数组(ArrayList)
动态数组(ArrayList)代表了可被单独索引的对象的有序集合。它基本上可以替代一个数组。但是,与数组不同的是,您可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。它也允许在列表中进行动态内存分配、增加、搜索、排序各项。
ArrayList 类的一些常用的属性:

属性 描述
Capacity 获取或设置 ArrayList 可以包含的元素个数。
Count 获取 ArrayList 中实际包含的元素个数。
IsFixedSize 获取一个值,表示 ArrayList 是否具有固定大小。
IsReadOnly 获取一个值,表示 ArrayList 是否只读。
Item 获取或设置指定索引处的元素。

ArrayList类的一些常用的方法:

序号 方法名 & 描述
1 public virtual int Add( object value ); 在 ArrayList 的末尾添加一个对象。
2 public virtual void AddRange( ICollection c ); 在 ArrayList 的末尾添加 ICollection 的元素。
3 public virtual void Clear();从 ArrayList 中移除所有的元素。
4 public virtual bool Contains( object item ); 判断某个元素是否在 ArrayList 中。
5 public virtual ArrayList GetRange( int index, int count ); 返回一个 ArrayList,表示源 ArrayList 中元素的子集。
6 public virtual int IndexOf(object);返回某个值在 ArrayList 中第一次出现的索引,索引从零开始。
7 public virtual void Insert( int index, object value ); 在 ArrayList 的指定索引处,插入一个元素。
8 public virtual void InsertRange( int index, ICollection c ); 在 ArrayList 的指定索引处,插入某个集合的元素。
9 public virtual void Remove( object obj ); 从 ArrayList 中移除第一次出现的指定对象。
10 public virtual void RemoveAt( int index ); 移除 ArrayList 的指定索引处的元素。
11 public virtual void RemoveRange( int index, int count ); 从 ArrayList 中移除某个范围的元素。
12 public virtual void Reverse();逆转 ArrayList 中元素的顺序。
13 public virtual void SetRange( int index, ICollection c ); 复制某个集合的元素到 ArrayList 中某个范围的元素上。
14 public virtual void Sort();对 ArrayList 中的元素进行排序。
15 public virtual void TrimToSize();设置容量为 ArrayList 中元素的实际个数。
  1. using System;
  2. using System.Collections;
  3. namespace ActiveArrayList
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. ArrayList al = new ArrayList();
  10. Console.WriteLine("Adding some numbers:");
  11. al.Add(45);
  12. al.Add(78);
  13. al.Add(33);
  14. al.Add(56);
  15. al.Add(12);
  16. al.Add(23);
  17. al.Add(9);
  18. Console.WriteLine("Capacity: {0} ", al.Capacity);
  19. Console.WriteLine("Count: {0}", al.Count);
  20. Console.Write("Source Content: ");
  21. foreach (int i in al)
  22. {
  23. Console.Write(i + " ");
  24. }
  25. Console.WriteLine();
  26. Console.Write("Sorted Content: ");
  27. al.Sort();
  28. foreach (int i in al)
  29. {
  30. Console.Write(i + " ");
  31. }
  32. Console.WriteLine();
  33. Console.ReadKey();
  34. }
  35. }
  36. }

结果:

  1. Adding some numbers:
  2. Capacity: 8
  3. Count: 7
  4. Source Content: 45 78 33 56 12 23 9
  5. Sorted Content: 9 12 23 33 45 56 78

(2) 哈希表(Hashtable)
Hashtable类代表了一系列基于键的哈希代码组织起来的键/值对。它使用键来访问集合中的元素。
当您使用键访问元素时,则使用哈希表,而且您可以识别一个有用的键值。哈希表中的每一项都有一个键/值对。键用于访问集合中的项目。
Hashtable 类的一些常用的属性:

属性 描述
Count 获取 Hashtable 中包含的键值对个数。
IsFixedSize 获取一个值,表示 Hashtable 是否具有固定大小。
IsReadOnly 获取一个值,表示 Hashtable 是否只读。
Item 获取或设置与指定的键相关的值。
Keys 获取一个 ICollection,包含 Hashtable 中的键。
Values 获取一个 ICollection,包含 Hashtable 中的值。

Hashtable 类的一些常用的方法:

序号 方法名 & 描述
1 public virtual void Add( object key, object value ); 向 Hashtable 添加一个带有指定的键和值的元素。
2 public virtual void Clear(); 从 Hashtable 中移除所有的元素。
3 public virtual bool ContainsKey( object key ); 判断 Hashtable 是否包含指定的键。
4 public virtual bool ContainsValue( object value ); 判断 Hashtable 是否包含指定的值。
5 public virtual void Remove( object key ); 从 Hashtable 中移除带有指定的键的元素。
  1. using System;
  2. using System.Collections;
  3. namespace HashtableUsing
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. Hashtable ht = new Hashtable();
  10. ht.Add("001", "Zara Ali");
  11. ht.Add("002", "Abida Rehman");
  12. ht.Add("003", "Joe Holzner");
  13. ht.Add("004", "Mausam Benazir Nur");
  14. ht.Add("005", "M. Amlan");
  15. ht.Add("006", "M. Arif");
  16. ht.Add("007", "Ritesh Saikia");
  17. if (ht.ContainsValue("Nuha Ali"))
  18. {
  19. Console.WriteLine("This student name is already in the list");
  20. }
  21. else
  22. {
  23. ht.Add("008", "Nuha Ali");
  24. }
  25. // 获取键的集合
  26. ICollection key = ht.Keys;
  27. foreach (string k in key)
  28. {
  29. Console.WriteLine(k + ": " + ht[k]);
  30. }
  31. Console.ReadKey();
  32. }
  33. }
  34. }

结果:

  1. 001: Zara Ali
  2. 002: Abida Rehman
  3. 003: Joe Holzner
  4. 004: Mausam Benazir Nur
  5. 005: M. Amlan
  6. 006: M. Arif
  7. 007: Ritesh Saikia
  8. 008: Nuha Ali

(3) 堆栈(Stack)
堆栈(Stack)代表了一个后进先出的对象集合。当您需要对各项进行后进先出的访问时,则使用堆栈。当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素。
Stack 类的一些常用的属性:

属性 描述
Count 获取 Stack 中包含的元素个数。

Stack 类的一些常用的方法:

序号 方法名 & 描述
1 public virtual void Clear(); 从 Stack 中移除所有的元素。
2 public virtual bool Contains( object obj ); 判断某个元素是否在 Stack 中。
3 public virtual object Peek();返回在 Stack 的顶部的对象,但不移除它。
4 public virtual object Pop();移除并返回在 Stack 的顶部的对象。
5 public virtual void Push( object obj );向 Stack 的顶部添加一个对象。
6 public virtual object[] ToArray();复制 Stack 到一个新的数组中。
  1. using System;
  2. using System.Collections;
  3. namespace StackUsing
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. Stack st = new Stack();
  10. st.Push('A');
  11. st.Push('M');
  12. st.Push('G');
  13. st.Push('W');
  14. Console.WriteLine("Current stack: ");
  15. foreach (char c in st)
  16. {
  17. Console.Write(c + " ");
  18. }
  19. Console.WriteLine();
  20. st.Push('V');
  21. st.Push('H');
  22. Console.WriteLine("The next poppable value in stack: {0}",
  23. st.Peek());
  24. Console.WriteLine("Current stack: ");
  25. foreach (char c in st)
  26. {
  27. Console.Write(c + " ");
  28. }
  29. Console.WriteLine();
  30. Console.WriteLine("Removing values ");
  31. st.Pop();
  32. st.Pop();
  33. st.Pop();
  34. Console.WriteLine("Current stack: ");
  35. foreach (char c in st)
  36. {
  37. Console.Write(c + " ");
  38. }
  39. Console.ReadKey();
  40. }
  41. }
  42. }

结果:

  1. Current stack:
  2. W G M A
  3. The next poppable value in stack: H
  4. Current stack:
  5. H V W G M A
  6. Removing values
  7. Current stack:
  8. G M A

(4) 队列(Queue)
队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。
Queue 类的一些常用的属性:

属性 描述
Count 获取 Queue 中包含的元素个数。

Queue 类的一些常用的属性:

序号 方法名 & 描述
1 public virtual void Clear(); 从 Queue 中移除所有的元素。
2 public virtual bool Contains( object obj ); 判断某个元素是否在 Queue 中。
3 public virtual object Dequeue();移除并返回在 Queue 的开头的对象。
4 public virtual void Enqueue( object obj ); 向 Queue 的末尾添加一个对象。
5 public virtual object[] ToArray();复制 Queue 到一个新的数组中。
6 public virtual void TrimToSize();设置容量为 Queue 中元素的实际个数。
  1. using System;
  2. using System.Collections;
  3. namespace QueueUsing
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. Queue q = new Queue();
  10. q.Enqueue('A');
  11. q.Enqueue('M');
  12. q.Enqueue('G');
  13. q.Enqueue('W');
  14. Console.WriteLine("Current queue: ");
  15. foreach (char c in q)
  16. Console.Write(c + " ");
  17. Console.WriteLine();
  18. q.Enqueue('V');
  19. q.Enqueue('H');
  20. Console.WriteLine("Current queue: ");
  21. foreach (char c in q)
  22. Console.Write(c + " ");
  23. Console.WriteLine();
  24. Console.WriteLine("Removing some values ");
  25. char ch = (char)q.Dequeue();
  26. Console.WriteLine("The removed value: {0}", ch);
  27. ch = (char)q.Dequeue();
  28. Console.WriteLine("The removed value: {0}", ch);
  29. Console.ReadKey();
  30. }
  31. }
  32. }

结果:

  1. Current queue:
  2. A M G W
  3. Current queue:
  4. A M G W V H
  5. Removing values
  6. The removed value: A
  7. The removed value: M

(5) 点阵列(BitArray)
BitArray 类管理一个紧凑型的位值数组,它使用布尔值来表示,其中 true 表示位是开启的(1),false 表示位是关闭的(0)。
当您需要存储位,但是事先不知道位数时,则使用点阵列。您可以使用整型索引从点阵列集合中访问各项,索引从零开始。
BitArray 类的一些常用的属性:

属性 描述
Count 获取 BitArray 中包含的元素个数。
IsReadOnly 获取一个值,表示 BitArray 是否只读。
Item 获取或设置 BitArray 中指定位置的位的值。
Length 获取或设置 BitArray 中的元素个数。

BitArray 类的一些常用的方法:

序号 方法名 & 描述
1 public BitArray And( BitArray value ); 对当前的 BitArray 中的元素和指定的 BitArray 中的相对应的元素执行按位与操作。
2 public bool Get( int index ); 获取 BitArray 中指定位置的位的值。
3 public BitArray Not();把当前的 BitArray 中的位值反转,以便设置为 true 的元素变为 false,设置为 false 的元素变为 true。
4 public BitArray Or( BitArray value ); 对当前的 BitArray 中的元素和指定的 BitArray 中的相对应的元素执行按位或操作。
5 public void Set( int index, bool value ); 把 BitArray 中指定位置的位设置为指定的值。
6 public void SetAll( bool value ); 把 BitArray 中的所有位设置为指定的值。
7 public BitArray Xor( BitArray value ); 对当前的 BitArray 中的元素和指定的 BitArray 中的相对应的元素执行按位异或操作。
  1. using System;
  2. using System.Collections;
  3. using System.Linq;
  4. namespace BitArrayUsing
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. // 创建两个大小为 8 的点阵列
  11. BitArray ba1 = new BitArray(8);
  12. BitArray ba2 = new BitArray(8);
  13. byte[] a = { 60 };
  14. byte[] b = { 13 };
  15. // 把值 60 和 13 存储到点阵列中
  16. ba1 = new BitArray(a);
  17. ba2 = new BitArray(b);
  18. // ba1 的内容
  19. Console.WriteLine("Bit array ba1: 60");
  20. for (int i = 0; i < ba1.Count; i++)
  21. {
  22. Console.Write("{0, -6} ", ba1[i]);
  23. }
  24. Console.WriteLine();
  25. // ba2 的内容
  26. Console.WriteLine("Bit array ba2: 13");
  27. for (int i = 0; i < ba2.Count; i++)
  28. {
  29. Console.Write("{0, -6} ", ba2[i]);
  30. }
  31. Console.WriteLine();
  32. BitArray ba3 = new BitArray(8);
  33. ba3 = ba1.And(ba2);
  34. // ba3 的内容
  35. Console.WriteLine("Bit array ba3 after AND operation: 12");
  36. for (int i = 0; i < ba3.Count; i++)
  37. {
  38. Console.Write("{0, -6} ", ba3[i]);
  39. }
  40. Console.WriteLine();
  41. ba3 = ba1.Or(ba2);
  42. // ba3 的内容
  43. Console.WriteLine("Bit array ba3 after OR operation: 61");
  44. for (int i = 0; i < ba3.Count; i++)
  45. {
  46. Console.Write("{0, -6} ", ba3[i]);
  47. }
  48. Console.WriteLine();
  49. Console.ReadKey();
  50. }
  51. }
  52. }

结果:

  1. Bit array ba1: 60
  2. False False True True True True False False
  3. Bit array ba2: 13
  4. True False True True False False False False
  5. Bit array ba3 after AND operation: 12
  6. False False True True False False False False
  7. Bit array ba3 after OR operation: 61
  8. True False True True False False False False
3.异常处理

异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应,比如尝试除以零。
异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。
(1 try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
(2 catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
(3 finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。例如,如果您打开一个文件,不管是否出现异常文件都要被关闭。
(4 throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。
使用 try/catch 语法如下所示:

  1. try
  2. {
  3. // 引起异常的语句
  4. }
  5. catch (ExceptionName e1)
  6. {
  7. // 错误处理代码
  8. }
  9. catch (ExceptionName e2)
  10. {
  11. // 错误处理代码
  12. }
  13. catch (ExceptionName eN)
  14. {
  15. // 错误处理代码
  16. }
  17. finally
  18. {
  19. // 要执行的语句
  20. }

注:您可以列出多个 catch 语句捕获不同类型的异常,以防 try 块在不同的情况下生成多个异常。
一些派生自 Sytem.SystemException 类的预定义的异常类:

异常类 描述
System.IO.IOException 处理 I/O 错误。
System.IndexOutOfRangeException 处理当方法指向超出范围的数组索引时生成的错误。
System.ArrayTypeMismatchException 处理当数组类型不匹配时生成的错误。
System.NullReferenceException 处理当依从一个空对象时生成的错误。
System.DivideByZeroException 处理当除以零时生成的错误。
System.InvalidCastException 处理在类型转换期间生成的错误。
System.OutOfMemoryException 处理空闲内存不足生成的错误。
System.StackOverflowException 处理栈溢出生成的错误。
  1. using System;
  2. namespace TryCatchAndSoOn
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. int result=0;
  9. int num1 = 20;
  10. int num2 = 0;
  11. try
  12. {
  13. result = num1 / num2;
  14. }
  15. catch (DivideByZeroException e)
  16. {
  17. Console.WriteLine("Exception caught: {0}", e);
  18. }
  19. finally
  20. {
  21. Console.WriteLine("Result: {0}", result);
  22. }
  23. Console.ReadKey();
  24. }
  25. }
  26. }

结果:

  1. Exception caught: System.DivideByZeroException: 尝试除以零。
  2. TryCatchAndSoOn.Program.Main(String[] args) 位置 F:\ChangFile\ChangDocument\ASP.NET基础及企业项目应用测试实例\第一章\第六节\TryCatchAndSoOn\Program.cs:行号 14
  3. Result: 0

第七节文件操作基础

一个文件是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个流。
从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流和输出流。输入流用于从文件读取数据(写操作),输出流用于向文件写入数据(读操作)。

1. C#的I/O 类

System.IO 命名空间有各种不同的类,用于执行各种文件操作,如创建和删除文件、读取或写入文件,关闭文件等。
System.IO 命名空间中常用的非抽象类:

I/O类 描述
BinaryReader 从二进制流读取原始数据。
BinaryWriter 以二进制格式写入原始数据。
BufferedStream 字节流的临时存储。
Directory 有助于操作目录结构。
DirectoryInfo 用于对目录执行操作。
DriveInfo 提供驱动器的信息。
File 有助于处理文件。
FileInfo 用于对文件执行操作。
FileStream 用于文件中任何位置的读写。
MemoryStream 用于随机访问存储在内存中的数据流。
Path 对路径信息执行操作。
StreamReader 用于从字节流中读取字符。
StreamWriter 用于向一个流中写入字符。
StringReader 用于读取字符串缓冲区。
StringWriter 用于写入字符串缓冲区。
2. FileStream类

System.IO 命名空间中的 FileStream 类有助于文件的读写与关闭。该类派生自抽象类 Stream。
您需要创建一个 FileStream 对象来创建一个新的文件,或打开一个已有的文件。创建 FileStream 对象的语法如下:

  1. FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
参数 描述
FileMode FileMode 枚举定义了各种打开文件的方法。FileMode 枚举的成员有:Append:打开一个已有的文件,并将光标放置在文件的末尾。如果文件不存在,则创建文件。Create:创建一个新的文件。如果文件已存在,则删除旧文件,然后创建新文件。CreateNew:指定操作系统应创建一个新的文件。如果文件已存在,则抛出异常。Open:打开一个已有的文件。如果文件不存在,则抛出异常。OpenOrCreate:指定操作系统应打开一个已有的文件。如果文件不存在,则用指定的名称创建一个新的文件打开。Truncate:打开一个已有的文件,文件一旦打开,就将被截断为零字节大小。然后我们可以向文件写入全新的数据,但是保留文件的初始创建日期。如果文件不存在,则抛出异常。
FileAccess FileAccess 枚举的成员有:Read、ReadWrite 和 Write。
FileShare FileShare 枚举的成员有:Inheritable:允许文件句柄可由子进程继承。Win32 不直接支持此功能。None:谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。Read:允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。ReadWrite:允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。Write:允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。Delete:允许随后删除文件。
  1. using System;
  2. using System.IO;
  3. namespace FileOperationUsing
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. FileStream F = new FileStream("test.txt",
  10. FileMode.OpenOrCreate, FileAccess.ReadWrite);//文件读写操作
  11. for (int i = 1; i <= 20; i++)
  12. {
  13. F.WriteByte((byte)i);//将i以Byte形式写入
  14. }
  15. F.Position = 0;
  16. for (int i = 0; i <= 20; i++)
  17. {
  18. Console.Write(F.ReadByte() + " ");//读出文件的数据
  19. }
  20. F.Close();
  21. Console.ReadKey();
  22. }
  23. }
  24. }

结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1

第八节自动聊天软件

Install-package Newtonsoft.json 添加此程序集的引用

  1. using Newtonsoft.Json;
  2. using System;
  3. using System.IO;
  4. using System.Net;
  5. using System.Text;
  6. using System.Windows.Forms;
  7. namespace tuling
  8. {
  9. public partial class Form1 : Form
  10. {
  11. const String KEY = "9d1c5997cdbd42bfaa693bbb3daca560"; //这里是注册时得到的key
  12. public static string HttpGet(string url, Encoding encoding)
  13. {
  14. string data = "";
  15. try
  16. {
  17. WebRequest request; //使用url发出请求的类
  18. request = WebRequest.Create(url);
  19. request.Credentials = CredentialCache.DefaultCredentials; //使用默认的身份验证
  20. request.Timeout = 10000; //设定超时
  21. WebResponse response; //提供响应的类
  22. response = request.GetResponse();
  23. data = new StreamReader(response.GetResponseStream(), encoding).ReadToEnd(); //获取数据
  24. }
  25. catch (System.Exception e)
  26. {
  27. Console.WriteLine(e.Message);
  28. }
  29. return data;
  30. }
  31. public Form1()
  32. {
  33. InitializeComponent();
  34. }
  35. private void button1_Click(object sender, EventArgs e)
  36. {
  37. String input = tbxInput.Text;
  38. string url = "http://www.tuling123.com/openapi/api?key=" + KEY + "&info=" + input;
  39. /* 清空输入框 */
  40. tbxInput.Text = "";
  41. /* 将输入内容放入聊天记录窗口中 */
  42. tbxHistory.AppendText("You: " + input + "\n");
  43. Encoding encoding = Encoding.GetEncoding("utf-8");
  44. String data = HttpGet(url, encoding);
  45. JsonReader reader = new JsonTextReader(new StringReader(data));
  46. while (reader.Read())
  47. {
  48. //tbxHistory.AppendText(reader.TokenType + "\t\t" + reader.ValueType + "\t\t" + reader.Value + "\n");
  49. if (reader.TokenType == JsonToken.PropertyName
  50. && reader.ValueType == Type.GetType("System.String")
  51. && Convert.ToString(reader.Value) == "code")
  52. {
  53. /* 如果当前Value是code,读取下一条,查看code的值 */
  54. reader.Read();
  55. switch (Convert.ToInt32(reader.Value))
  56. {
  57. case 100000:
  58. /* 返回码为文本类数据 */
  59. reader.Read();
  60. reader.Read();
  61. tbxHistory.AppendText("Robot: " + reader.Value + "\n");
  62. break;
  63. default:
  64. break;
  65. }
  66. }
  67. }
  68. }
  69. private void tbxInput_KeyDown(object sender, KeyEventArgs e)
  70. {
  71. if (e.KeyCode == Keys.Enter)
  72. {
  73. button1_Click(sender,e);
  74. }
  75. }
  76. }
  77. }

效果如图:

image.png

课程附件

附件

下一篇



版权所有:机遇屋在线 Copyright © 2021-2025 jiyuwu Co., Ltd.

鲁ICP备16042261号-1