1.C#简介
·C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言、运行于.NET Framework和.NET Core(完全开源、跨平台)之上的高级程序设计语言。
·C#是一种安全的、稳定的、简单的、优雅的面向对象编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性。
2.C#基本语法
(1)using关键字
在任何C#程序中的第一条语句都是:
using System;
(2)class关键字
class关键字用于声明一个类
(3)C#中的注释
在 C# 程序中,多行注释以 /* 开始,并以字符 */ 终止。单行注释是用 ‘//’ 符号表示。
(4)成员变量
变量是类的属性或数据成员,用于存储数据。
(5)标识符
标识符是用来识别类、变量、函数或任何其他用户定义的项目。在C#中,类的命名必须遵循以下基本规则:
-
·标识符必须以字母、下划线或 @ 开头,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。
-
·标识符中的第一个字符不能是数字。 标识符必须不包含任何嵌入的空格或符号,比如 ? - +! # % ^ & * ( ) [ ] { }
. ; : " ’ / \。 -
·标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
-
·标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
-
·不能与C#的类库名称相同。
(6)C#关键字
关键字是C#编译器预定义的保留字。这些关键字不能用作标识符,如果想使用关键字作为标识符,可以在关键字前面加上@字符作为前缀。
3.C#数据类型
在C#中,变量分为以下几种类型:
- 值类型(Value types)
- 引用类型(Reference types)
- 指针类型(Pointer types)
1.值类型(Value types)
值类型变量可以直接分配给一个值。它们是从类System.Value Type中派生的。
值类型直接包含数据。比如int、char、float,它们分别存储数字、字符、浮点数。当声明一个int类型时,系统分配内存来存储值。
下表为C#2010中可用的值类型:
——引用自菜鸟教程
2.引用类型(Reference types)
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
在使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值得变化。内置的引用类型有: object、dynamic和string。
(1)对象object 类型
对象类型是C#通用类型系统(Common Type System - CTS)中所有数据类型的终极基类。
Object是System.Object类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。
但是,在分配值之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为装箱;另一方面、,当一个对象类型转换为值类型时,则被称为拆箱。
Eg:
object obj;
obj=100; //这是装箱
(2)动态(Dynamic)类型
声明动态类型的语法:
dynamic <variable_name> =value;
Eg:
dynamic d=20;
注:
动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的。而动态类型变量的类型检查实在运行时发生的。
(3)字符串(String)类型
字符串类型允许给变量分配任何字符串值。
字符串(String)类型是System.String类的别名。
它是从对象(Object)类型派生的。
字符串(String)类型的值可以通过两种形式进行分配: 引号和@引号。
例如:
String str =“runoob.com”;
一个@引号字符串:
@“runoob.com”;
C#string字符串的前面可以加@(称作“逐字字符串”)将转义字符(\)当作普通字符对待,比如:
string str = @“C: \Windows”;
等价于:
string str = “C: \Windows”;
用户自定义引用类型有:class、interface或delegate。
(3)指针类型(Pointer types)
指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type * identifier;
Eg:
char* cprt;
int* iptr;
4.C#创建对象和对象的使用
(1)实例化方法,也就是new();
(2)Activator 创建实例;
(3)反射创建实例;
注意: 其中第一和第二效率高,第三由于是反射,效率略低。
5.C#中public和private访问权限控制
-
public关键字是类型和类型成员的访问修饰符。公共访问是允许的最高访问级别,对访问公共成员没有限制。
-
public修饰的类,可以在整个系统的任意地方调用,是完全公开的。
-
private关键字是一个成员访问修饰符。私有访问是允许的最低访问级别。私有成员只有在声明它们的类和结构体中才是可访问的。
-
private关键字以为着除了该类型的创建者和类的内部成员函数之外,任何人都不能存取这些成员。
-
private只能在类内部调用,任何实例,无法调用private调用。
6.C#中什么是构造函数
(1)构造函数的定义
构造函数是在创建给定类型的对象时执行的类方法。构造函数具有与类相同的名称,它通常初始化新对象的数据成员。不带参数的构造函数称为“默认构造函数”。无论什么时候,只要使用new运算符实例化对象,并且不为new提供任何参数,就会调用默认构造函数。除非类是静态的,否则C#编译器将为无构造函数的类提供了一个公共的默认构造函数,以便该类中可以实例化。默认构造函数:public 类名(){}
构造函数可分为:实例构造函数、静态构造函数、私有构造函数
(2)构造函数注意事项
- 构造函数没有返回值(void也不需要)
- 一个类中可以有多个构造函数,可根据其参数个数,参数顺序,参数类型的不同来区分它们,这称作构造函数的重载
- 构造函数的命名必须和类名相同
- 调用子类的构造函数时会先调用父类的无参构造函数
- 通常使用构造函数来进行类中字段的赋初值
- 构造函数不能直接被调用,必须通过关键字new在创建对象时自动调用
- 当一个类没有定义任何构造函数时,C#编译器会自动为其生成一个默认的隐式无参构造函数
- 如果一个类中定义了有参构造函数,实例化时需要调用无参构造函数,这时我们就必须定义一个显式无参数构造函数,否则运行会报错
(3)构造函数与一般函数的区别
①声明方式不同
构造函数:
[访问修饰符] 类名(参数列表){函数主体}
一般函数:
[访问修饰符] 返回类型 方法名(参数列表){函数主体}
②调用方式不同
构造函数: 在类实例化时调用
一般函数: 在类实例化后,必须手动调用
7.C#属性和匿名类型
(1)属性是类(class)、结构(structure)和接口(interface)的命名(named)成员。类或结构中的成员变量或方法称为域(Field)。
属性是域的扩展,且可使用相同的语法来访问。
它们使用访问器
让私有域的值可被读写或操作。
属性不会确定确定存储位置。相反,它们具有可读写或计算它们值的访问器(accessors)
。
访问器(accessors)
- 访问器包含有助于获取(读取或计算)或设置(写入)属性的可执行语句。
- 访问器 声明可包含一个get访问器、一个set访问器,或者同时包含二者。
(2)匿名类型
- 在C#中,
匿名类型是一种没有任何名称的类型(类),只能包含公共只读属性。
它不能包含其他成员,例如字段、方法、事件等。 - 可以使用带有对象初始值语法的new运算符创建匿名类型。隐式类型变量var用于保存匿名类型的引用。
- 匿名类型的属性是只读的,不能用空、匿名函数或指针类型初始化。可以使用点(.)表示法访问属性,与对象属性相同。但不能修改属性的值,因为是只读属性。
- 大多数情况下,匿名类型是使用LINQ查询的Select子句创建的,以从集合中的每个对象返回属性的子集。
- 所有匿名类型同都是直接从System.Object类派生。编译器会为它自动生成一些名字,并根据值表达式将适当的类型应用于每个属性。使用
GetType()方法
查看名称。
8.C#什么是继承
- 继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时有利于重用代码和节省开发时间。
- 当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个
已有的类
被称为的基类
,这个新的类
被称为派生类
。
(1)基类和派生类
一个类可以派生自多个类和接口,这意味着它可以从多个基类或接口继承数据和函数。
C#中创建派生类的语法:
<访问修饰符> class <基类>
{
...
}
class <派生类> : <基类>
{
...
}
Eg:
(2)基类的初始化
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。可以在成员初始化列表中进行父类的初始化。
(3)C#多重继承
- 多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。
- C#不支持多重继承。但可以使用接口来实现多重继承。
9.C#中this和base关键字
-
this可以访问当前类中定义的字段,属性和方法,不管有没有this都可以进行访问。但是使用this可以让IDE给出方法名的提示方便快捷。
-
另外,当方法的参数跟字段重名时,使用this可以表明访问的是类中的字段。
-
this可以访问当前类中的所有属性和方法,包括其继承来的父类中的所有属性和方法(前提是有继承关系。)
-
base 可以调用当前类中的父类中的字段、属性和方法,不管有没有base都可以进行访问。
-
调用父类的同名属性、方法。
-
调用父类指定的构造函数。
-
用在子类中访问父类的成员。
10.C#中关于虚方法Virtual
一、虚方法的定义
当有一个定义在类中的函数需要再继承类中实现时,可以使用虚方法,虚方法是使用关键字virtual
声明的,虚方法可以再不同的继承类中有不同的实现,即为基类中定义的允许再派生类中重写的方法;
二、虚方法的声明
声明形式:
访问修饰符 virtual 函数返回类型 函数名(参数表){函数体};
三、虚方法的注意事项
①只有为虚方法时可以进行重写,不能对非虚方法进行重写;
②虚方法在形式上在方法名前加virtual
修饰;
③虚方法一般在基类定义,在派生类中实现具体操作,派生类实现该方法时,要用override
对其方法进行修饰;
④当用virtual修饰后,不允许再有static
、abstract
或者override
修饰符;
四、虚方法的作用
①允许子类/派生类进行重写;
②增加代码的可维护性,脉络较清晰有条理;
11.C#中什么是接口
- 接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同"是什么"部分,派生类定义了语法合同"怎么做"部分。
- 接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。
- 接口使得实现接口的类或结构在形式上保持一致。
- 接口使用
interface
关键字声明,它与类的声明类似。接口声明默认是public
的。
12.C#中什么是索引器
- 索引器(Indexer) 允许一个对象可以像数组一样使用下标的方式来访问。
- 当为类定义一个索引器时,该类的行为就会像一个虚拟数组(virtual array) 一样。可以使用数组访问运算符
[ ]
来访问该类的成员。 - 语法:
element-type this [int index]
{
//get 访问器
get
{
//返回index指定的值
}
//set 访问器
set
{
//设置index指定的值
}
}
- 索引器的用途
索引器的行为的声明在某种程度上类似于属性(property)。就像属性(property),您可使用
get 和 set 访问器
来定义索引器。但是,属性返回或设置一个特定的数据成员,而索引器返回或设置对象实例的一个特定值。换句话说,它把实例数据分为更小的部分,并索引每个部分,获取或设置每个部分。定义一个属性(property)包括提供属性名称。索引器定义的时候不带有名称,但带有 this 关键字,它指向对象实例。
- 重载索引器
索引器可被重载。
索引器声明的时候也可带有多个参数,且每个参数可以是不同的类型。没有必要让索引器必须是整型的。C#允许索引器可以是其他类型。
13.C#中泛型
-
泛型(Generic) 允许延迟编写类或方法中的变成元素的数据类型的规范,直到实际在程序中使用它的时候。也就是说,泛型允许编写一个可以与任何数据类型一起工作的类或方法。
-
泛型的特性 :
①有助于最大限度的重用代码、保护类那个的安全以及提高性能。
②可以创建泛型集合类。.NET框架类库在System.Collections.Generic命名空间中包含了一些新的泛型集合类。可以使用这些泛型集合类来替代System.Collections中的集合类。
③可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
④可以对泛型类进行约束以访问特定数据类型的方法。
⑤关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。