C基础复习重点.doc

上传人:小** 文档编号:630044 上传时间:2019-04-22 格式:DOC 页数:21 大小:218KB
返回 下载 相关 举报
C基础复习重点.doc_第1页
第1页 / 共21页
C基础复习重点.doc_第2页
第2页 / 共21页
点击查看更多>>
资源描述

《C基础复习重点.doc》由会员分享,可在线阅读,更多相关《C基础复习重点.doc(21页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、-_C# 基础知识点基础知识点1、 数据类型数据类型 1.1、值类型、引用类型 1.2、预定义类型 1.3、类型转换 1.4、装箱和拆箱 2、 变量、常量变量、常量 2.1、变量 2.2、常量 3、 运算符和表达式运算符和表达式 3.1、运算符、表达式 3.2、特殊运算符 3.3、优先级别 4、 流程控制流程控制 4.1、条件语句 4.2、循环语句 4.3、跳转语句 4.4、异常处理 5、 程序结构程序结构 5.1、类 5.2、命名空间 5.3、Main 方法 6、程序例子、程序例子 7、作业、作业一一 数据类型数据类型1.1 值类型、引用类型值类型、引用类型C# 的数据类型可以分成两大部分:

2、值类型和引用类型。 值类型的变量总是直接包含着自身的数据,而引用类型的变量是指向实际数据的地址。C# 值类型包括:整型、布尔型、实型、十进制型、结构和枚举、接口和数组。 从概念上看,其区别是值类型直接存储其值,而引用类型存储对值的引用。这两种类型存 储在内存的不同地方:值类型存储在堆栈中,而引用类型存储在托管堆上。注意区分某个 类型是值类型还是引用类型,因为这种存储位置的不同会有不同的影响。例如,int 是值类 型,这表示下面的语句会在内存的两个地方存储值 20:/ i 和 j 都是整型变量 i = 20; j = i; 但考虑下面的代码。这段代码假定已经定义了一个类 class1,class

3、1 是一个引用类型,它有-_一个 int 类型的成员变量 Value:class1 x, y x = new class1 (); x.Value = 30; y = x; Console.WriteLine(y.Value);/输出 30 y.Value = 50; Console.WriteLine(x.Value);/输出 50 要理解的重要一点是在执行这段代码后,只有一个 class1 对象。x 和 y 都指向包含该对象 的内存位置。因为 x 和 y 是引用类型的变量,声明这两个变量只是保留了一个引用而 不会实例化给定类型的对象。因为 x 和 y 引用同一个对象,所以对 x 的修改会影

4、响 y,反 之亦然。因此上面的代码会显式 30 和 50。 如果变量是一个引用,就可以把其值设置为 null,确定它不引用任何对象: y = null; 在 C#中,基本数据类型如 bool 和 long 都是值类型。如果声明一个 bool 变量,并给它赋予 另一个 bool 变量的值,在内存中就会有两个 bool 值。如果以后修改第一个 bool 变量的值, 第二个 bool 变量的值也不会改变。这些类型是通过值来复制的。相反,大多数更复杂的 C#数据类型,包括我们自己声明的类都是引用类型。它们分配在堆中,其生存期可以跨多 个函数调用,可以通过一个或几个别名来访问。CLR(Common La

5、nguage Runtime 公共语 言运行库指.NET 的运行时支持,包括一个面向对象类型系统和一些运行时服务)执行一种 精细的算法来跟踪哪些引用变量仍是可以访问的,哪些引用变量已经不能访问了。CLR 会 定期进行清理,删除不能访问的对象,把它们占用的内存返回给操作系统。这是通过垃圾 收集器实现的。1.2 预定义类型预定义类型C#认可的基本预定义类型并没有内置于语言中,而是内置于.NET Framework 中。例如, 在 C#中声明一个 int 类型的数据时,声明的实际上是.NET 结构 System.Int32 的一个实例。 C#支持两个预定义的引用类型,如下表: CTS:公共类型系统名

6、 称CTS 类说 明ObjectSystem.Object根类型,其他类型都是从它派生而来的(包括值类型) StringSystem.StringUnicode 字符串1. object 类型类型在 C#中,object 类型就是最终的父类型,所有内在和用户定义的类型都从它派生而来。这 是 C#的一个重要特性, object 类型就可以用于两个目的: 可以使用 object 引用绑定任何特定子类型的对象。 object 类型执行许多基本的一般用途的方法,包括 Equals()、GetHashCode()、 GetType()和 ToString()。用户定义的类可能需要使用一种面向对象技术 重

7、写, 提供其中一些方法的替代执行方法。例如,重写 ToString()时,要给类提供一个方-_法,该方法可以提供类本身的字符串表示。如果类中没有提供这些方法的实现,编 译器就会在对象中选择这些实现,它们在类中的执行不一定正确。2. string 类型类型C#有 string 关键字,在翻译为.NET 类时,它就是 System.string。有了它,像字符串连接和 字符串复制这样的操作就很简单了:string str1 = “Hello “; string str2 = “World“; string str3 = str1 + str2; / 字符串连接 尽管这是一个值类型的赋值,但 str

8、ing 是一个引用类型。String 对象保留在堆上,而不是堆 栈上。因此,当把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的 两个引用。但是,string 与引用类型在常见的操作上有一些区别。例如,修改其中一个字符 串,注意这会创建一个全新的 string 对象,而另一个字符串没有改变。考虑下面的代码:using System; class StringExample public static int Main()string s1 = “a string“;string s2 = s1;Console.WriteLine(“s1 is “ + s1);Console.Wr

9、iteLine(“s2 is “ + s2);s1 = “another string“;Console.WriteLine(“s1 is now “ + s1);Console.WriteLine(“s2 is now “ + s2);return 0; 其输出结果为:s1 is a strings2 is a strings1 is now another strings2 is now a string换言之,改变 s1 的值对 s2 没有影响,这与我们期待的引用类型正好相反。1.3 类型转换类型转换1.隐式转换隐式转换隐式转换就是系统默认的、不需要加以声明就可以进行的转换。 隐式转换一

10、般不 会失败,转换过程中也不会导致信息丢失。 隐式转换包括下面几种:-_2.显式转换显式转换显式类型转换,就是强制类型转换。与隐式转换正好相反,显式转换需要用户明 确指定转换的类型,不如看下面例子:long l = 5000;int I = (int)l; 显式转换可以发生在表达式的计算过程中。它并不是总能成功,而且常常可能引 起信息丢失。显式转换包括所有的隐式转换。 显式转换包括下面几种:1.4 装箱和拆箱装箱和拆箱装箱和拆箱使我们可以把一个值类型当作一个引用类型看待。装箱转换是指将一个值 类型隐式的转换成一个 Object 类型,拆箱转换是指将一个 Object 类型显式地转换成一个值 类

11、型,他们互为逆过程。 装箱(boxing) 装箱转换是指将一个值类型隐式转换成一个 object 类型,或者把这个值类型转换成一 个被该值类型应用的接口类型。把一个值类型的值装箱,也就是创建一个 object 实例并将 这个值给这个 objet.不如:-_Int i = 10;Object obj = i; 拆箱(unboxing) 拆箱转换是指将一个对象类型显式转换成一个值类型,或是将一个接口类型显示地转 换成一个执行该接口的值类型。 拆箱的过程分为两步:首先,检查这个对象的实例,看它是否为给定的值类型的装箱 值。然后,把这个实例的值拷贝给值类型的变量。如:Int i = 10;Object

12、 obj = i;Int j = (int)obj;二二 变量、常量变量、常量2.1、变量、变量在 C#中声明变量使用下述语法:datatype identifier;例如: int i; 一旦它被声明之后,就可以使用赋值运算符(=)给它分配一个值: i = 10;还可以在一行代码中声明变量,并初始化它的值: int i = 10; 如果在一个语句中声明和初始化了多个变量,那么所有的变量都具有相同的数据类型:int x = 10, y =20; 要声明类型不同的变量,需要使用单独的语句。在多个变量的声明中,不能指定不同的数据类型:int x = 10; bool y = true; int x

13、 = 10, bool y = true; / 这样编译报错1.变量的初始化变量的初始化变量的初始化是 C#强调安全性的另一个例子。简单地说,C#编译器需要用某个初始值对变量进行初始化,之后才能在操作中引用该变量。大多数现代编译器把没有初始化标记为警告,但 C#编译器把它当作错误来看待。这就可以防止我们无意中从其他程序遗留下来的内存中获取垃圾值。 C#有两个方法可确保变量在使用前进行了初始化: 变量是类或结构中的字段,如果没有显式进行初始化,在默认状态下当创建这些 变量时,其值就是 0。 方法的局部变量必须在代码中显式初始化,之后才能在语句中使用它们的值。此 时,初始化不是在声明该变量时进行的

14、,但编译器会通过方法检查所有可能的路径, 如果检测到局部变量在初始化之前就使用了它的值,就会产生错误。 同样的规则也适用于引用类型。考虑下面的语句:Something objSomething;-_在 C#中,这行代码仅会为 Something 对象创建一个引用,但这个引用还没有指向任何对象。 对该变量调用方法或属性会导致错误。 在 C#中实例化一个引用对象需要使用 new 关键字。如上所述,创建一个引用,使用 new 关键字把该引用指向存储在堆上的一个对象:objSomething = new Something(); / This creates a Something on the he

15、ap2.变量的变量的作用域作用域变量的作用域是可以访问该变量的代码区域。一般情况下,确定作用域有以下规则: 只要字段所属的类在某个作用域内,其字段(也称为成员变量)也在该作用域内局部 变量存在于表示声明该变量的块语句或方法结束的封闭花括号之前的作用域内。 在 for、while 或类似语句中声明的局部变量存在于该循环体内。局部变量的作用域冲突大型程序在不同部分为不同的变量使用相同的变量名是很常见的。只要变量的作用域是程 序的不同部分,就不会有问题,也不会产生模糊性。但要注意,同名的局部变量不能在同 一作用域内声明两次,所以不能使用下面的代码:int x = 20; / 其它代码 int x =

16、 30;字段和局部变量的作用域冲突在某些环境下,可以区分名称相同(尽管不是经过完全限定的名称)、作用域相同的两个标识符。此时编译器允许声明第二个变量。原因是 C#使得变量之间有一个基本的区分,它把声明为类型级的变量看作是字段,而把在方法中声明的变量看作局部变量。2.2、常量、常量在声明和初始化变量时,在变量的前面加上关键字 const,就可以把该变量指定为一个常量。 顾名思义,常量是其值在使用过程中不会发生变化的变量:const int a = 100; /变量的值不能改变C#中只能把局部变量和字段声明为常量。常量具有如下特征: 常量必须在声明时初始化。指定了其值后,就不能再修改了。 常量的值

17、必须能在编译时用于计算。因此,不能用从一个变量中提取的值来初始 化常量。如果需要这么做,应使用只读字段。 常量用易于理解的清楚的名称替代了“含义不明确的数字或字符串”,使程序更 易于阅读。 常量使程序更易于修改。例如,在 C#程序中有一个 SalesTax 常量,该常量的值为 6%。如果以后销售税率发生变化,可以把新值赋给这个常量,就可以修改所有的 税款计算,而不必查找整个程序,修改税率为 0.06 的每个项。 常量更容易避免程序出现错误。如果要把另一个值赋给程序中的一个常量,而该 常量已经有了一个值,编译器就会报告错误。-_三三 运算符和表达式运算符和表达式3.1、运算符、表达式、运算符、表

18、达式算术操作符和算术表达式 加法操作符 减法操作符* 乘法操作符/ 除法操作符 求余法操作符 例:加法表达式Enum Weekday Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday; Weekday day1 = weekday.Sunday; Weekday day2 = day1+2; Console.WriteLine(day2);结果是: Tuesday赋值运算符 * / -_虽然,字符型不能转换为字符串类型,程序可以通过,不过有一个警告。位运算改运算符还有其 它更多的用法,具体如下: 在 C# 中,new 关键字可用作

19、运算符、修饰符或约束。 1)new 运算符:用于创建对象和调用构造函数。这种大家都比较熟悉,没什么好说的了。2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。 3)new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。 关于第二种用法看下例:using System;namespace ConsoleApplication1public class BaseApublic int x = 1;public void Invoke()Console.WriteLine(x.ToString();-_public int TrueValueget retur

20、n x; set x = value; public class DerivedB : BaseAnew public int x = 2;new public void Invoke()Console.WriteLine(x.ToString();new public int TrueValueget return x; set x = value; class Teststatic void Main(string args)DerivedB b = new DerivedB();b.Invoke();/调用 DerivedB 的 Invoke 方法,输出:2Console.WriteLi

21、ne(b.x.ToString();/输出 DerivedB 的成员 x 值:2BaseA a = b;a.Invoke();/调用 BaseA 的 Invoke 方法,输出:1a.TrueValue = 3;/调用 BaseA 的属性TrueValue,修改 BaseA 的成员 x 的值Console.WriteLine(a.x.ToString();/输出 BaseA 的成员 x 的值:3Console.WriteLine(b.TrueValue.ToString();/输出 DerivedB 的成员 x 的值,仍然是:1/可见,要想访问被隐藏的基类的成员变量、属性或方法,办法就是将子类造

22、型为父类,然/后通过基类访问被隐藏的成员变量、属性或方法。new 约束指定泛型类声明中的任何类型参数都必须具有公共的无参数构造函数.请看下例:using System;using System.Collections.Generic;namespace ConsoleApplication2-_public class Employeeprivate string name;private int id;public Employee()name = “Temp“;id = 0;public Employee(string s, int i)name = s;id = i;public str

23、ing Nameget return name; set name = value; public int IDget return id; set id = value; class ItemFactory where T : new()public T GetNewItem()return new T();public class Testpublic static void Main()ItemFactory EmployeeFactory = new ItemFactory();/此处编译器会检查 Employee 是否具有公有的无参构造函数。-_/若没有则会有 The Employe

24、e must have a public parameterless constructor 错误。Console.WriteLine(“0ID is 1.“, EmployeeFactory.GetNewItem().Name, EmployeeFactory.GetNewItem().ID);Typeof 操作符用于获得系统原形对象的类型。 如: typeof(int) 等于 int32.Checked 和 unchecked 操作符Checked 和 unchecked 操作符用于整形算术运算时控制当前环境中的溢出检查。Const int x = 1000000;Const int y

25、= 1000000;Return checked(x * y) /编译时会报溢出错误 3.3、优先级别、优先级别当一个表达式包含多个操作符时,操作符的优先级控制着单个操作符的求值顺序。-_四四 流程控制流程控制4.1、条件语句、条件语句条件语句可以根据条件是否满足或根据表达式的值控制代码的执行分支。C#有两个 分支代码的结构:if 语句,测试特定条件是否满足;switch 语句,它比较表达式和许多不 同的值。1. if 语句语句语法都是非常直观的:if (condition)statement(s)elsestatement(s)还可以单独使用 if 语句,不加 else 语句。也可以合并 e

26、lse if 子句,测试多个条件。2. switch 语句语句switch.case 语句适合于从一组互斥的分支中选择一个执行分支。其形式是 switch 参数的后 面跟一组 case 子句。如果 switch 参数中表达式的值等于某个 case 子句旁边的某个值,就执 行该 case 子句中的代码。此时不需要使用花括号把语句组合到块中;只需使用 break 语句 标记每个 case 代码的结尾即可。也可以在 switch 语句中包含一个 default 子句,如果表达 式不等于其他 case 子句的值,就执行 default 子句的代码。下面的 switch 语句测试 integerA 变量

27、的值:switch (integerA) case 1:Console.WriteLine(“integerA =1“);break;case 2:Console.WriteLine(“integerA =2“);break;case 3:Console.WriteLine(“integerA =3“);break;default:Console.WriteLine(“integerA is not 1,2, or 3“);break; 注意 case 的值必须是常量表达式不允许使用变量。-_4.2、循环语句、循环语句C#提供了 4 种不同的循环机制(for、while、do.while 和

28、foreach),在满足某个条件之前, 可以重复执行代码块。1. for 循环循环C#的 for 循环提供的迭代循环机制是在执行下一次迭代前,测试是否满足某个条件,其语 法如下:for (initializer; condition; iterator)statement(s)其中: initializer 是指在执行第一次迭代前要计算的表达式(通常初始化为一个局部变量, 作为循环计数器); condition 是在每次迭代循环前要测试的表达式(它必须等于 true,才能执行下一次 迭代); iterator 是每次迭代完要计算的表达式(通常是递增循环计数器)。当 condition 等于 f

29、alse 时,迭代停止。 for 循环是所谓的预测试循环,因为循环条件是在执行循环语句前计算的,如果循环条件为 假,循环语句就根本不会执行。 for 循环非常适合用于一个语句或语句块重复执行预定的次数。下面的例子就是使用 for 循 环的典型用法,这段代码输出从 099 的整数:for (int i = 0; i 0) i -;sum += i; -_3. dowhile 循环循环do.while 循环是 while 循环的后测试版本。do.while 循环适合于至少执行一次循环体的情 况:int i = 10, sum = 0;doi-;sum += i; while (i 0);4. fo

30、r each 循环循环foreach 循环是我们讨论的最后一种 C#循环机制。也是非常受欢迎的一种循环。从下面的代码中可以了解 foreach 循环的语法,其中假定 arrayOfInts 是一个整型数组:int numbers = 4, 5, 6, 1, 2, 3, -2, -1, 0 ;foreach (int i in numbers)System.Console.WriteLine(i); 其中,foreach 循环一次迭代数组中的一个元素。对于每个元素,它把该元素的值放在 int型的变量 temp 中,然后再执行一次循环迭代。如果需要迭代集合中的各项,并改变它们的值,就应使用 for

31、 循环。4.3、跳转语句、跳转语句C#提供了许多可以立即跳转到程序中另一行代码的语句,在此,先介绍 goto 语句。1. goto 语句语句goto 语句可以直接跳转到程序中用标签指定的另一行(标签是一个标识符,后跟一个冒号):goto Label1;Console.WriteLine(“This wont be executed“); Label1:Console.WriteLine(“Continuing execution from here“);goto 语句有两个限制。不能跳转到像 for 循环这样的代码块中,也不能跳出类的范围, 不能退出 try.catch 块后面的 finall

32、y 块。goto 语句的名声不太好,在大多数情况下不允许 使用它。一般情况下,使用它肯定不是面向对象编程的好方式。 前面简要提到过 break 语句在 switch 语句中使用它退出某个 case 语句。实际上,break 也可以用于退出 for、foreach、while 或 do.while 循环,循环结束后,立即执行后面的语句。-_如果该语句放在嵌套的循环中,就执行最内部循环后面的语句。如果 break 放在 switch 语句或循环外部,就会产生编译时错误。2. continue 语句语句continue 语句类似于 break,也必须用于 for、foreach、while 或 do

33、.while 循环中。但它只 从循环的当前迭代中退出,然后从循环的下一次迭代开始重新执行,而不是退出循环。3. return 语句语句return 语句用于退出类的方法,把控制返回方法的调用者,如果方法有返回类型,return 语 句必须返回这个类型的值,如果方法没有返回类型,应使用没有表达式的 return 语句。4.4、异常处理、异常处理Try catch(s) Try finally Try catch(s) finally-_五五 程序结构程序结构5.1、类、类C中的类是对数据结构的封装,是 C最重要的组成部分。我们利用类定义各种 新的数据类型,其中既包含数据内容,有包含数据操作,封装

34、之后,类可以控制外界 对它成员的访问。 类的静态成员属于类,非静态成员属于这个类的某个实例。 在一个类的实例对象的生命周期中,最先执行的代码是类的构造函数,构造 函数总是用来初始化对象的特殊类型的函数。 不带参数的类的构造函数对类的实例的初始化始固定的,我们也可以使用带参数 的构造函数,通过向他传递参数来对类的不同实例进行不同的初始化。构造函数同样 也可以使用默认参数。 当这个类的实例超出了作用域的时候,或者由于其它理由被破坏时,析构函数将 释放分配给该实例的任何存储区。5.2、命名空间、命名空间命名空间提供了一种组织相关类和其它类型的方式。与文件或组件不同,命名空 间时一种逻辑组合,而不是物

35、理组合,在 C文件中定义类时,可以把它包含在命名 空间的定义中,以后在定义另一个类,在另一个文件中执行相关操作时,就可以在同 一个命名空间中包含它,创建一个逻辑组合,告诉其它使用类的开发人员如何使类相 关,和对他们进行使用。命名空间可以嵌套。如: Namespace A Namespace B Namespace C代码块 每个命名空间名都由他所在的命名空间的名称组成,这些名称用句号隔开,首先是最 外层,最后是自己的名字。如:上面的例子也可以写成: Namespace A. B. C 代码块-_ 不允许在另一个嵌套的命名空间中声明多部分的命名空间。也不能在同一命名空间中 有两个同名的类。5.3

36、、Main 方法方法C#程序是从方法 Main()开始执行的。这个方法必须是类或结构的静态方法,并且其返 回类型必须是 int 或 void。虽然显式指定 public 修饰符是很常见的,因为按照定义,必须 在程序外部调用该方法,但我们给该方法指定什么访问级别并不重要,即使把该方法标记 为 private,它也可以运行。 在调用程序时,可以让 CLR 包含一个参数,将命令行参数转送给程序。这个参数是一个字 符串数组,传统称为args(但 C#可以接受任何名称)。在启动程序时,可以使用这个数组, 访问通过命令行传送过来的选项。 下面的例子 ArgsExample.cs 是在传送给 Main 方法

37、的字符串数组中迭代,并把每个选项 的值写入控制台窗口:using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication2class Programstatic void Main(string args)for (int i = 0; i 、=、!=、=c. 不允许被重载的操作符:using System.Collections.Generic;using System.Text;namespace ConsoleApplication1class Playerpublic

38、int neili;public int tili;public int jingyan;public int r_neili;public int r_tili;public Player()neili = 10;-_tili = 50;jingyan = 0;r_neili = 50;r_tili = 50;public static Player operator +(Player p)p.neili = p.neili + 50;p.tili = p.tili + 100;/p.r_neili = p.r_neili;/p.r_tili = p.r_tili;return p;publ

39、ic void Show()Console.WriteLine(“Tili:0“, tili);class Testpublic static void Main()Player man = new Player();man.Show();man+;Console.WriteLine(“Now upgrading.“);man.Show();-_七七 作业作业一、基础概念理解题。 (红色为必做题,其余选做) 1.静态变量和非静态变量的区别? 2.const 和 static readonly 区别? 3.extern 是什么意思? 4.abstract 是什么意思? 5.internal 修饰

40、符起什么作用? 6.sealed 修饰符是干什么的? 7.override 和 overload 的区别? 8.什么是索引指示器? 9.new 修饰符是起什么作用? 10.this 关键字的含义? 11.可以使用抽象函数重写基类中的虚函数吗? 12.密封类可以有虚函数吗? 13.如果基类中的虚属性只有一个属性访问器,那么继承类重写该属性后可以有几个属 性访问器?如果基类中有 get 和 set 两个呢? 14.abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗? 15.接口可以包含哪些成员? 16.类和结构的区别? 17.接口的多继承会带来哪些问题? 18.抽象类和接口的区别? 19.别名指示符是什么? 20.如何释放非托管资源? 21.P/Invoke 是什么? 22.StringBuilder 和 String 的区别? 23.explicit 和 implicit 的含义? 24.params 有什么用? 25.什么是反射? 二、写程序练习循环、判断语句,运算符、函数重载,类的继承,out 参数。 (知识点必须 练完,可以在一个程序例子中完成,也可以写多个例子练习) 。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com