C#基础教程

CC 4.0 BY-SA

    <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b5506197d8.css">
            <div id="content_views" class="htmledit_views">
                <pre><code class="language-html hljs xml"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> /* 我的第一个 C# 程序*/</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">      Console.WriteLine("Hello World!");</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">      Console.ReadKey();</div></div></li></ol></code><div class="hljs-button {2}" data-title="复制" data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.4259&quot;}" onclick="hljs.copyCode(event)"></div></pre> 

编写 Console.Readkey(); 这个函数是为了在控制台窗口停留一下,直到敲击键盘为止。

不然运行时,"Hello World!" 这句话会在控制台窗口一闪而过,没法查看。

 

1.C# 简介

.Net 框架的一部分。

.Net 框架(.Net Framework)

.Net 框架是一个创新的平台,能帮您编写出下面类型的应用程序:

  • Windows 应用程序
  • Web 应用程序
  • Web 服务

一个 C# 程序主要包括以下部分:

  • 命名空间声明(Namespace declaration)
  • 一个 class
  • Class 方法
  • Class 属性
  • 一个 Main 方法
  • 语句(Statements)& 表达式(Expressions)
  • 注释

 

  • 程序的第一行 using System; - using 关键字用于在程序中包含 System 命名空间。 一个程序一般有多个 using 语句。
  • 下一行是 namespace 声明。一个 namespace 是一系列的类。HelloWorldApplication 命名空间包含了类 HelloWorld
  • 下一行是 class 声明。类 HelloWorld 包含了程序使用的数据和方法声明。类一般包含多个方法。方法定义了类的行为。在这里,HelloWorld 类只有一个 Main 方法。
  • 下一行定义了 Main 方法,是所有 C# 程序的 入口点Main 方法说明当执行时 类将做什么动作。

 

2.C# 基本语法


 
 
  1. using System;
  2. namespace RectangleApplication
  3. {
  4. class Rectangle
  5. {
  6. // 成员变量
  7. double length;
  8. double width;
  9. public void Acceptdetails()
  10. {
  11. length = 4.5;
  12. width = 3.5;
  13. }
  14. public double GetArea()
  15. {
  16. return length * width;
  17. }
  18. public void Display()
  19. {
  20. Console.WriteLine("Length: {0}", length);
  21. Console.WriteLine("Width: {0}", width);
  22. Console.WriteLine("Area: {0}", GetArea());
  23. }
  24. }
  25. class ExecuteRectangle
  26. {
  27. static void Main(string[] args)
  28. {
  29. Rectangle r = new Rectangle();
  30. r.Acceptdetails();
  31. r.Display();
  32. Console.ReadLine();
  33. }
  34. }
  35. }

成员变量

变量是类的属性或数据成员,用于存储数据。在上面的程序中,Rectangle 类有两个成员变量,名为 length 和 width。

成员函数

函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。我们举例的类 Rectangle 包含了三个成员函数: AcceptDetails、GetArea 和 Display。

实例化一个类

在上面的程序中,类 ExecuteRectangle 是一个包含 Main() 方法和实例化 Rectangle 类的类。

 

3.C# 数据类型

在 C# 中,变量分为以下几种类型:

  • 值类型(Value types)
  • 引用类型(Reference types)
  • 指针类型(Pointer types)

 

3.1 值类型(Value types)

值类型直接包含数据。比如 int、char、float,它们分别存储数字、字符、浮点数。当您声明一个 int 类型时,系统分配内存来存储值。

 

3.2 引用类型(Reference types)

内置的 引用类型有:objectdynamic 和 string

当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱


 
 
  1. object obj;
  2. obj = 100; // 这是装箱

 

动态(Dynamic)类型

您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。


 
 
  1. dynamic <variable_name> = value;
  2. dynamic d = 20;

动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。

 

3.3 字符串(String)类型

字符串(String)类型的值可以通过两种形式进行分配:引号和 @引号。


 
 
  1. String str = "runoob.com";
  2. string str = @"C:\Windows";

 

指针类型(Pointer types)

指针类型变量存储另一种类型的内存地址


 
 
  1. type* identifier;
  2. char* cptr;
  3. int* iptr;

 

4. C# 类型转换

  • 隐式类型转换 - 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
  • 显式类型转换 - 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失。

 

4.1 C# 类型转换方法

C# 提供了下列内置的类型转换方法:

  1. ToBoolean 如果可能的话,把类型转换为布尔型。
  1. ToByte 把类型转换为字节类型。
  1. ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型。
  1. ToDateTime
  1. ToDecimal 把浮点型或整数类型转换为十进制类型。
  1. 。。。

 

5. C# 变量

 

C# 中的变量定义


 
 
  1. int i, j, k;
  2. char c, ch;
  3. float f, salary;
  4. double d;

 

接受来自用户的值

System 命名空间中的 Console 类提供了一个函数 ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中。例如:


 
 
  1. int num;
  2. num = Convert.ToInt32(Console.ReadLine());

函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据

 

6.C# 常量

 

整数常量

整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。

整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。

这里有一些整数常量的实例:


 
 
  1. 212 /* 合法 */
  2. 215u /* 合法 */
  3. 0xFeeL /* 合法 */
  4. 078 /* 非法:8 不是一个八进制数字 */
  5. 032UU /* 非法:不能重复后缀 */

 


 
 
  1. 85 /* 十进制 */
  2. 0213 /* 八进制 */
  3. 0x4b /* 十六进制 */
  4. 30 /* int */
  5. 30u /* 无符号 int */
  6. 30l /* long */
  7. 30ul /* 无符号 long */

 

浮点常量

一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。

 

字符常量

字符常量是括在单引号里,例如,'x',且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 'x')、一个转义序列(例如 '\t')或者一个通用字符

 

7. C# 运算符

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符
  • c = a++: 先将 a 赋值给 c,再对 a 进行自增运算。
  • c = ++a: 先将 a 进行自增运算,再将 a 赋值给 c 。
  • c = a--: 先将 a 赋值给 c,再对 a 进行自减运算。
  • c = --a: 先将 a 进行自减运算,再将 a 赋值给 c 。
 Console.WriteLine("c 的值是 {0}", c);
 
 

 

 

7.1 关系运算

 

7.2 逻辑运算符

 

 

7.3 位运算符

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:

 

 

7.4 赋值运算符

 

7.5 其他运算符

下表列出了 C# 支持的其他一些重要的运算符,包括 sizeoftypeof 和 ? :

 

7.6 C# 中的运算符优先级

 

 

8. C# 封装

C# 支持的访问修饰符如下所示:

  • public:所有对象都可以访问;
  • private:对象本身在对象内部可以访问;
  • Private 访问修饰符允许一个类将其成员变量和成员函数对其他的函数和对象进行隐藏。只有同一个类中的函数可以访问它的私有成员。即使是类的实例也不能访问它的私有成员。
  • protected:只有该类对象及其子类对象可以访问
  • Protected 访问修饰符允许子类访问它的基类的成员变量和成员函数。这样有助于实现继承
  • internal:同一个程序集的对象可以访问;
  • nternal 访问说明符允许一个类将其成员变量和成员函数暴露给当前程序中的其他函数和对象。换句话说,带有 internal 访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问。
  • protected internal:访问限于当前程序集或派生自包含类的类型。

 

9. C# 方法

要使用一个方法,您需要:

  • 定义方法
  • 调用方法

 
 
  1. <Access Specifier> <Return Type> <Method Name>(Parameter List)
  2. {
  3. Method Body
  4. }
  • Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
  • Return type:返回类型,一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void
  • Method name:方法名称,是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同。
  • Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说,一个方法可能不包含参数。
  • Method body:方法主体,包含了完成任务所需的指令集。

 

按引用传递参数

引用参数是一个对变量的内存位置的引用。当按引用传递参数时,与值参数不同的是,它不会为这些参数创建一个新的存储位置。引用参数表示与提供给方法的实际参数具有相同的内存位置。

在 C# 中,使用 ref 关键字声明引用参数。下面的实例演示了这点:


 
 
  1. using System;
  2. namespace CalculatorApplication
  3. {
  4. class NumberManipulator
  5. {
  6. public void swap(ref int x, ref int y)
  7. {
  8. int temp;
  9. temp = x; /* 保存 x 的值 */
  10. x = y; /* 把 y 赋值给 x */
  11. y = temp; /* 把 temp 赋值给 y */
  12. }
  13. static void Main(string[] args)
  14. {
  15. NumberManipulator n = new NumberManipulator();
  16. /* 局部变量定义 */
  17. int a = 100;
  18. int b = 200;
  19. Console.WriteLine("在交换之前,a 的值: {0}", a);
  20. Console.WriteLine("在交换之前,b 的值: {0}", b);
  21. /* 调用函数来交换值 */
  22. n.swap(ref a, ref b);
  23. Console.WriteLine("在交换之后,a 的值: {0}", a);
  24. Console.WriteLine("在交换之后,b 的值: {0}", b);
  25. Console.ReadLine();
  26. }

 

按输出传递参数

return 语句可用于只从函数中返回一个值。但是,可以使用 输出参数 来从函数中返回两个值。输出参数会把方法输出的数据赋给自己,其他方面与引用参数相似

 


 
 
  1. using System;
  2. namespace CalculatorApplication
  3. {
  4. class NumberManipulator
  5. {
  6. public void getValue(out int x )
  7. {
  8. int temp = 5;
  9. x = temp;
  10. }
  11. static void Main(string[] args)
  12. {
  13. NumberManipulator n = new NumberManipulator();
  14. /* 局部变量定义 */
  15. int a = 100;
  16. Console.WriteLine("在方法调用之前,a 的值: {0}", a);
  17. /* 调用函数来获取值 */
  18. n.getValue(out a);
  19. Console.WriteLine("在方法调用之后,a 的值: {0}", a);
  20. Console.ReadLine();
  21. }
  22. }

 

 

C# 可空类型(Nullable)

? : 单问号用于对 int,double,bool 等无法直接赋值为 null 的数据类型进行 null 的赋值,意思是这个数据类型是 NullAble 类型的。

 


 
 
  1. int? i = 3
  2. 等同于
  3. Nullable <int> i = new Nullable <int>(3);
  4. int i; //默认值0
  5. int? ii; //默认值null

?? : 双问号 可用于判断一个变量在为 null 时返回一个指定的值。

Nullable< bool > 变量可以被赋值为 true 或 false 或 null。

< data_type> ? <variable_name> = null;
 
 

 


 
 
  1. int? num1 = null;
  2. int? num2 = 45;
  3. double? num3 = new double?();
  4. double? num4 = 3.14157;
  5. bool? boolval = new bool?();
  6. // 显示值
  7. Console.WriteLine("显示可空类型的值: {0}, {1}, {2}, {3}",
  8. num1, num2, num3, num4);
  9. Console.WriteLine("一个可空的布尔值: {0}", boolval);
  10. Console.ReadLine();

 


 
 
  1. 显示可空类型的值: , 45, , 3.14157
  2. 一个可空的布尔值:

 

Null 合并运算符( ?? )

如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值


 
 
  1. using System;
  2. namespace CalculatorApplication
  3. {
  4. class NullablesAtShow
  5. {
  6. static void Main(string[] args)
  7. {
  8. double? num1 = null;
  9. double? num2 = 3.14157;
  10. double num3;
  11. num3 = num1 ?? 5.34; // num1 如果为空值则返回 5.34
  12. Console.WriteLine("num3 的值: {0}", num3);
  13. num3 = num2 ?? 5.34;
  14. Console.WriteLine("num3 的值: {0}", num3);
  15. Console.ReadLine();
  16. }
  17. }
  18. }

 


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

 

 10. C# 数组(Array)

datatype[] arrayName;
 
 
  • datatype 用于指定被存储在数组中的元素的类型。
  • [ ] 指定数组的秩(维度)。秩指定数组的大小。
  • arrayName 指定数组的名称。

 

初始化数组

声明一个数组不会在内存中初始化数组。当初始化数组变量时,您可以赋值给数组。

数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。

double[] balance = new double[10];
 
 

 


 
 
  1. using System;
  2. namespace ArrayApplication
  3. {
  4. class MyArray
  5. {
  6. static void Main(string[] args)
  7. {
  8. int [] n = new int[10]; /* n 是一个带有 10 个整数的数组 */
  9. int i,j;
  10. /* 初始化数组 n 中的元素 */
  11. for ( i = 0; i < 10; i++ )
  12. {
  13. n[ i ] = i + 100;
  14. }
  15. /* 输出每个数组元素的值 */
  16. for (j = 0; j < 10; j++ )
  17. {
  18. Console.WriteLine("Element[{0}] = {1}", j, n[j]);
  19. }
  20. Console.ReadKey();
  21. }
  22. }

 


 
 
  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

 

使用 foreach 循环


 
 
  1. using System;
  2. namespace ArrayApplication
  3. {
  4. class MyArray
  5. {
  6. static void Main(string[] args)
  7. {
  8. int [] n = new int[10]; /* n 是一个带有 10 个整数的数组 */
  9. /* 初始化数组 n 中的元素 */
  10. for ( int i = 0; i < 10; i++ )
  11. {
  12. n[i] = i + 100;
  13. }
  14. /* 输出每个数组元素的值 */
  15. foreach (int j in n )
  16. {
  17. int i = j-100;
  18. Console.WriteLine("Element[{0}] = {1}", i, j);
  19. }
  20. Console.ReadKey();
  21. }

 

11. C# 多维数组

C# 支持多维数组。多维数组又称为矩形数组。

您可以声明一个 string 变量的二维数组,如下:

string [,] names;
 
 

或者,您可以声明一个 int 变量的三维数组,如下:

int [ , , ] m;
 
 

 

初始化二维数组

多维数组可以通过在括号内为每行指定值来进行初始化。下面是一个带有 3 行 4 列的数组。


 
 
  1. int [,] a = new int [3,4] {
  2. {0, 1, 2, 3} , /* 初始化索引号为 0 的行 */
  3. {4, 5, 6, 7} , /* 初始化索引号为 1 的行 */
  4. {8, 9, 10, 11} /* 初始化索引号为 2 的行 */
  5. };

 

C# 传递数组给函数

在 C# 中,您可以传递数组作为函数的参数

 


 
 
  1. using System;
  2. namespace ArrayApplication
  3. {
  4. class MyArray
  5. {
  6. double getAverage(int[] arr, int size)
  7. {
  8. int i;
  9. double avg;
  10. int sum = 0;
  11. for (i = 0; i < size; ++i)
  12. {
  13. sum += arr[i];
  14. }
  15. avg = (double)sum / size;
  16. return avg;
  17. }
  18. static void Main(string[] args)
  19. {
  20. MyArray app = new MyArray();
  21. /* 一个带有 5 个元素的 int 数组 */
  22. int [] balance = new int[]{1000, 2, 3, 17, 50};
  23. double avg;
  24. /* 传递数组的指针作为参数 */
  25. avg = app.getAverage(balance, 5 ) ;
  26. /* 输出返回值 */
  27. Console.WriteLine( "平均值是: {0} ", avg );
  28. Console.ReadKey();
  29. }

 

C# 参数数组

参数数组通常用于传递未知数量的参数给函数。

C# 提供了 params 关键字,使调用数组为形参的方法时,既可以传递数组实参,也可以传递一组数组元素。params 的使用格式为:


 
 
  1. public 返回类型 方法名称( params 类型名称[] 数组名称 )
  2. using System;
  3. namespace ArrayApplication
  4. {
  5. class ParamArray
  6. {
  7. public int AddElements(params int[] arr)
  8. {
  9. int sum = 0;
  10. foreach (int i in arr)
  11. {
  12. sum += i;
  13. }
  14. return sum;
  15. }
  16. }
  17. class TestClass
  18. {
  19. static void Main(string[] args)
  20. {
  21. ParamArray app = new ParamArray();
  22. int sum = app.AddElements(512, 720, 250, 567, 889);
  23. Console.WriteLine("总和是: {0}", sum);
  24. Console.ReadKey();
  25. }
  26. }

 

12. C# Array 类

 

Array 类的属性

IsFixedSize

获取一个值,该值指示数组是否带有固定大小。

IsReadOnly

获取一个值,该值指示数组是否只读

Length

获取一个 32 位整数,该值表示所有维度的数组中的元素总数。

LongLength

获取一个 64 位整数,该值表示所有维度的数组中的元素总数。

Rank

获取数组的秩(维度)。

 

Array 类的方法

Clear

根据元素的类型,设置数组中某个范围的元素为零、为 false 或者为 null。

 

C# 结构体

 

定义结构体

为了定义一个结构体,您必须使用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。

例如,您可以按照如下的方式声明 Book 结构:


 
 
  1. struct Books
  2. {
  3. public string title;
  4. public string author;
  5. public string subject;
  6. public int book_id;
  7. };

补充:类与结构体的区别

1、结构体中声明的字段无法赋予初值,类可以:

结构体的构造函数中,必须为结构体所有字段赋值

 

类的对象是存储在堆空间中,结构存储在栈中。堆空间大,但访问速度较慢,栈空间小,访问速度相对更快。故而,当我们描述一个轻量级对象的时候,结构可提高效率,成本更低。当然,这也得从需求出发,

 

13. C# 枚举(Enum)

enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
 
 

C# 枚举是值类型


 
 
  1. using System;
  2. namespace EnumApplication
  3. {
  4. class EnumProgram
  5. {
  6. enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
  7. static void Main(string[] args)
  8. {
  9. int WeekdayStart = (int)Days.Mon;
  10. int WeekdayEnd = (int)Days.Fri;
  11. Console.WriteLine("Monday: {0}", WeekdayStart);
  12. Console.WriteLine("Friday: {0}", WeekdayEnd);
  13. Console.ReadKey();
  14. }
  15. }
  16. }

 


 
 
  1. Monday: 1
  2. Friday: 5

 

C# 类(Class)

对象是类的实例。构成类的方法和变量成为类的成员。

类的默认访问标识符是 internal,成员的默认访问标识符是 private

  • 如果要访问类的成员,你要使用点(.)运算符。
  • 点运算符链接了对象的名称和成员的名称。

 
 
  1. using System;
  2. namespace BoxApplication
  3. {
  4. class Box
  5. {
  6. public double length; // 长度
  7. public double breadth; // 宽度
  8. public double height; // 高度
  9. }
  10. class Boxtester
  11. {
  12. static void Main(string[] args)
  13. {
  14. Box Box1 = new Box(); // 声明 Box1,类型为 Box
  15. Box Box2 = new Box(); // 声明 Box2,类型为 Box
  16. double volume = 0.0; // 体积
  17. // Box1 详述
  18. Box1.height = 5.0;
  19. Box1.length = 6.0;
  20. Box1.breadth = 7.0;
  21. // Box2 详述
  22. Box2.height = 10.0;
  23. Box2.length = 12.0;
  24. Box2.breadth = 13.0;
  25. // Box1 的体积
  26. volume = Box1.height * Box1.length * Box1.breadth;
  27. Console.WriteLine("Box1 的体积: {0}", volume);
  28. // Box2 的体积
  29. volume = Box2.height * Box2.length * Box2.breadth;
  30. Console.WriteLine("Box2 的体积: {0}", volume);
  31. Console.ReadKey();
  32. }
  33. }

 

C# 中的构造函数

类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。

构造函数的名称与类的名称完全相同,它没有任何返回类型。


 
 
  1. using System;
  2. namespace LineApplication
  3. {
  4. class Line
  5. {
  6. private double length; // 线条的长度
  7. public Line()
  8. {
  9. Console.WriteLine("对象已创建");
  10. }
  11. public void setLength( double len )
  12. {
  13. length = len;
  14. }
  15. public double getLength()
  16. {
  17. return length;
  18. }
  19. static void Main(string[] args)
  20. {
  21. Line line = new Line();
  22. // 设置线条长度
  23. line.setLength(6.0);
  24. Console.WriteLine("线条的长度: {0}", line.getLength());
  25. Console.ReadKey();
  26. }
  27. }

 

C# 类的静态成员

关键字 static 意味着类中只有一个该成员的实例


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

 

将类成员函数声明为public static无需实例化即可调用类成员函数


 
 
  1. using System;
  2. namespace ConsoleApp
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. int num = AddClass.Add(2, 3); //编译通过
  9. Console.WriteLine(num);
  10. }
  11. }
  12. class AddClass
  13. {
  14. public static int Add(int x,int y)
  15. {
  16. return x + y;
  17. }
  18. }

 

 

15. C# 继承

当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类

 

基类和派生类

一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。

假设,有一个基类 Shape,它的派生类是 Rectangle:


 
 
  1. using System;
  2. namespace InheritanceApplication
  3. {
  4. class Shape
  5. {
  6. public void setWidth(int w)
  7. {
  8. width = w;
  9. }
  10. public void setHeight(int h)
  11. {
  12. height = h;
  13. }
  14. protected int width;
  15. protected int height;
  16. }
  17. // 派生类
  18. class Rectangle: Shape
  19. {
  20. public int getArea()
  21. {
  22. return (width * height);
  23. }
  24. }
  25. class RectangleTester
  26. {
  27. static void Main(string[] args)
  28. {
  29. Rectangle Rect = new Rectangle();
  30. Rect.setWidth(5);
  31. Rect.setHeight(7);
  32. // 打印对象的面积
  33. Console.WriteLine("总面积: {0}", Rect.getArea());
  34. Console.ReadKey();
  35. }
  36. }

 

C# 不支持多重继承。但是,您可以使用接口来实现多重继承。

 


 
 
  1. using System;
  2. namespace InheritanceApplication
  3. {
  4. class Shape
  5. {
  6. public void setWidth(int w)
  7. {
  8. width = w;
  9. }
  10. public void setHeight(int h)
  11. {
  12. height = h;
  13. }
  14. protected int width;
  15. protected int height;
  16. }
  17. // 基类 PaintCost
  18. public interface PaintCost
  19. {
  20. int getCost(int area);
  21. }
  22. // 派生类
  23. class Rectangle : Shape, PaintCost
  24. {
  25. public int getArea()
  26. {
  27. return (width * height);
  28. }
  29. public int getCost(int area)
  30. {
  31. return area * 70;
  32. }
  33. }
  34. class RectangleTester
  35. {
  36. static void Main(string[] args)
  37. {
  38. Rectangle Rect = new Rectangle();
  39. int area;
  40. Rect.setWidth(5);
  41. Rect.setHeight(7);
  42. area = Rect.getArea();
  43. // 打印对象的面积
  44. Console.WriteLine("总面积: {0}", Rect.getArea());
  45. Console.WriteLine("油漆总成本: ${0}" , Rect.getCost(area));
  46. Console.ReadKey();
  47. }
  48. }

 

C# 多态性

C# 提供了两种技术来实现静态多态性。分别为:

  • 函数重载
  • 运算符重载

 

函数重载

您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。

 

动态多态性

C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。

下面的程序演示了一个抽象类:


 
 
  1. using System;
  2. namespace PolymorphismApplication
  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 RectangleTester
  24. {
  25. static void Main(string[] args)
  26. {
  27. Rectangle r = new Rectangle(10, 7);
  28. double a = r.area();
  29. Console.WriteLine("面积: {0}",a);
  30. Console.ReadKey();
  31. }
  32. }
  33. }

 

 

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

动态多态性是通过 抽象类 和 虚方法 实现的

 

继承类中的重写虚函数需要声明关键字 override

 

 

C# 运算符重载

 operator 后跟运算符的符号来定义的

 


 
 
  1. public static Box operator+ (Box b, Box c)
  2. {
  3. Box box = new Box();
  4. box.length = b.length + c.length;
  5. box.breadth = b.breadth + c.breadth;
  6. box.height = b.height + c.height;
  7. return box;
  8. }

 

C# 接口(Interface)

接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。

接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。下面是一个接口声明的实例:


 
 
  1. interface IMyInterface
  2. {
  3. void MethodToImplement();
  4. }

以上代码定义了接口 IMyInterface。通常接口命令以 I 字母开头

 

接口继承: InterfaceInheritance.cs

以下实例定义了两个接口 IMyInterface 和 IParentInterface。

如果一个接口继承其他接口,那么实现类或结构就需要实现所有接口的成员。

以下实例 IMyInterface 继承了 IParentInterface 接口,因此接口实现类必须实现 MethodToImplement() 和 ParentInterfaceMethod() 方法:


 
 
  1. using System;
  2. interface IParentInterface
  3. {
  4. void ParentInterfaceMethod();
  5. }
  6. interface IMyInterface : IParentInterface
  7. {
  8. void MethodToImplement();
  9. }
  10. class InterfaceImplementer : IMyInterface
  11. {
  12. static void Main()
  13. {
  14. InterfaceImplementer iImp = new InterfaceImplementer();
  15. iImp.MethodToImplement();
  16. iImp.ParentInterfaceMethod();
  17. }
  18. public void MethodToImplement()
  19. {
  20. Console.WriteLine("MethodToImplement() called.");
  21. }
  22. public void ParentInterfaceMethod()
  23. {
  24. Console.WriteLine("ParentInterfaceMethod() called.");

 

C# 异常处理

  • try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
  • catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
  • finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。例如,如果您打开一个文件,不管是否出现异常文件都要被关闭。
  • throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值