C#语言基础
C#语言基础
标识符与关键字
namespace WelcomYou
{
class Program
{
static void Main(string[] args)
{
//定义输出文本变量
string welcomeText = "欢迎你";
//输出文本到控制台
Console.WriteLine(welcomeText);
//让控制台程序可见,直到按下任意字符为止
Console.ReadKey();
}
}
}
如上代码块,字符串
WelcomYou
,Program
,Main
,args
,welcomeText
都是标识符.
C#中标识符命名规则
- 只包含字母(包括大小写),数字,@符号以及下划线"_";
- 首位可以为字母,下划线,和@字符,但不能是数字
- 不能为C#关键字
C#关键字
基础数据类型
- 值类型
- 简单类型
- 有符号的整型:
sbyte
、short
、int
、long
- 无符号的整型:
byte
、ushort
、uint
、ulong
- Unicode 字符:
char
- IEEE 浮点:
float
、double
- 高精度小数:
decimal
- 布尔:
bool
- 有符号的整型:
- 枚举类型
- 格式为
enum E {...}
的用户定义类型
- 格式为
- 结构类型
- 格式为
struct S {...}
的用户定义类型
- 格式为
- 可以为
null
的值类型- 值为
null
的其他所有值类型的扩展
- 值为
- 简单类型
- 引用类型
- 类类型
- 其他所有类型的最终基类:
object
- Unicode 字符串:
string
- 格式为
class C {...}
的用户定义类型
- 其他所有类型的最终基类:
- 接口类型
- 格式为
interface I {...}
的用户定义类型
- 格式为
- 数组类型
- 一维和多维,例如
int[]
和int[,]
- 一维和多维,例如
- 委托类型
- 格式为
delegate int D(...)
的用户定义类型
- 格式为
- 类类型
数值类型
- 有符号的整型
sbyte
:8 位,介于 -128 到 127 之间short
:16 位,介于 -32,768 到 32,767 之间int
:32 位,介于 -2,147,483,648 到 2,147,483,647 之间long
:64位,介-2^63
到(2^63)-1
之间
- 无符号的整型
byte
:8 位,介于 0 到 255 之间ushort
:16 位,介于 0 到(2^16)-1
之间uint
:32 位,介于 0 到(2^23)-1
之间ulong
:64 位,介于 0 到(2^63)-1
之间
- 浮点型
float
:32 位,介于1.5 × 10^-45
到3.4 × 10^38
之间,7 位精度double
:64 位,介于5.0 × 10^-324
到1.7 × 10^308
之间,15 位精度
- 十进制
decimal
:128 位,至少介于-7.9 × 10^-28
到7.9×10^28
之间,至少为 28 位精度
布尔类型
- 布尔类型用于存储布尔值
false
,true
字符串类型
string(字符串)
是System.String
的别名(因此String
和string
是等效的),表示由零个或多个Unicode字符组成的不可变序列.可使用[]
运算符访问string
中的每个字符string
类型具有不可变性
枚举类型
- 用于声明一组命名了的常数
- 使用
enum
关键字声明
//定义性别枚举 enum Gender { //女 Female, //男 Male }
- 默认情况下,枚举中的每个元素都是
int
类型.用户可通过使用冒号,制定一种全新的数值类型.
//性别枚举 enum Gender:byte { //女 Female, //男 Male }
- 枚举使用
Gender c = Gender.Female;
- 使用
结构体类型
- 结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。
struct
关键字用于创建结构体.
public struct Point { public int x; public int y; public Point(int px,int py) { x = px; y = py; } }
- 结构体调用
Point a = new Point(10, 10); Point b = a; a.x = 20; Console.WriteLine(b.x); //如果 Point 是类,则输出 20,因为 a 和 b 引用同一对象。 如果 Point 是结构,则输出 10,因为将 a 赋值给 b 创建了值副本,而此副本不受后面对 a.x 的赋值的影响。
变量和常量
- 变量
- 变量代表一块内存空间,它存储的值时可以变化的
- 变量声明语法
数据类型 变量名;
- 常量
- 常量一但被初始化就不能再次改变
- 使用
const
关键字对常量进行定义
const 数据类型 常量名=与数据类型相对应的值;
- 声明并初始化常量得注意一下几点
- 因为后续无法更改,常量必须在声明时就初始化;
- 常量无法接受赋值,即使是readonly(只读)也不行
- 常量默认是静态的,不允许显式使用
static
关键字来声明
运算符和表达式
运算符
- 运算符是用于操作一个或多个操作数的程序元素
- 运算符优先级
- 运算符重载
- 使用自己已定义的类型为操作数时,使用运算符重载(运算符重载只能用于类或结构中),使用关键字
operator
- 例子:二元运算符重载
class Program { static void Main(string[] args) { //初始化两个复数 Complex number1 = new Complex(1, 2); Complex number2 = new Complex(3, 4); //使用+运算符都两个复数进行相加 //如果复数类型中没有对+运算符进行重载,则此处将不能使用+运算符来对复数类型进行相加操作 Complex sum = number1 + number2; //输出输入的复数和相加之后的结果 Console.WriteLine("第一个复数为{0}",number1); Console.WriteLine("第二个复数为{0}", number2); //二复数之和 Console.WriteLine("二复数之和为{0}", sum); Console.Read(); } } /// <summary> /// Complex属于自定义结构体 /// </summary> public struct Complex { //复数的实数部分 public int real; //复数的虚数部分 public int imaginary; //带参数的构造函数,real表示实数,imaginary表示虚数 public Complex(int real,int imaginary) { //初始化复数的实数和虚数 this.real = real; this.imaginary = imaginary; } /// <summary> /// +运算符重载方法 /// </summary> /// <param name="complex1">表示第一操作数,类型必须为Complex类型</param> /// <param name="complex2">表示第二操作数,类型必须为Complex类型</param> /// <returns>返回Complex类型</returns> public static Complex operator +(Complex complex1,Complex complex2) { //值类型都有默认无参构造函数 //通过无参构造函数进行初始化 Complex result = new Complex(); //对复数的实数和虚数赋值 result.real = complex1.real + complex2.real; result.imaginary = complex1.imaginary + complex2.imaginary; //返回复数相加结果 return result; } /// <summary> /// 重写ToString()方法 /// </summary> /// <returns></returns> public override string ToString() { return string.Format("{0}+{1}i",real,imaginary); } } //控制台输出结果 //第一个复数为:1+2i //第一个复数为:3+4i //两复数为:4+6i
- 运算符可重载性
- 使用自己已定义的类型为操作数时,使用运算符重载(运算符重载只能用于类或结构中),使用关键字
- 运算符优先级
C#中的语句
条件语句
if
语句switch
语句
循环语句
while
语句do-while
语句for
语句foreach
语句- 用于遍历数组或对象集合中的元素(只有实现了
System.Collections.IEnumber
和System.Collections.Generic.IEnumberable<T>
接口的数组或对象集合才可以是有foreach
)
- 用于遍历数组或对象集合中的元素(只有实现了
跳转语句
break
语句:直接退出整个循环continue
语句:立即终止本次循环,但会继续执行下一次循环goto
语句:跳出循环到已标记好的位置上return
语句:退出循环和循环所在函数
C#中的类
什么是类
- 类代表一组具有公共属性和行为的对象
- 使用
class
关键字定义类
class Person
{
//类成员定义
}
类访问修饰符
- 默认修饰符是
internal
- 无或
internal
:只能同一程序集中访问 public
:同一程序或引用该程序集的其他程序集可以访问类abstract
或interna abstract
:只能在同一程序集中访问类,该类不能被实例化,只能被继承public abstract
:同一程序或引用该程序集的其他程序集中访问类,该类不能被实例化,只能被继承sealed
或internal sealed
:只能在同一程序集中访问类,该类只能被实例化,不能被继承public sealed
: abstract`:同一程序或引用该程序集的其他程序集中访问类,该类只能被实例化,不能被继承
类成员
-
类成员包括字段,属性,方法和构造函数等
-
类成员访问修饰符
public
:同一程序集或引用该程序集的其他程序集都可以访问private
:只能同一类中可以访问protected
:只能同一个类或派生类中可以访问internal
:只能同一程序集中可以访问protected internal
:在同一个程序集,该类和派生类中可访问
-
字段
public class Person
{
//私有只读字段
private redonly string name;
//公共不可变字段
public const int age =18;
}
- 属性
- 属性是对字段的扩展
public clas Person { //私有字段定义 private string name; //公共属性定义 public string Name { //get访问器 get { return name; } //set 访问器 set { //value是隐式参数 name=value; } } private int age; //只读属性定义 public int Age { get { return age; } private set { age=value; } } }
- 当属性仅包含
set
访问器,或get
访问器,或set
访问器为private
级别时,这样的属性被称为只读属性.当属性仅包含set
访问器,或get
访问器为private
级别时,这样的属性被称为只写属性.
- 方法
- 一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。
- 定义方法
访问修饰符 返回值类型 方法名(方法参数) { .... //有返回类型的: return 返回值; }
- 调用方法
- 方法被
static
关键字声明为静态方法时调用
类名.方法名();
- 非静态方法调用
//先实例化一个对象 类名 p=new 类名() //再使用对象名调用方法 p.方法名();
- 方法被
- 方法重载
- 同名不同参(参数类型,数量不一样的),返回类型不属于方法签名一部分,所以不同也不受影响
- 构造函数
- 构造函数主要用于创建类的实例对象,当调用构造函数创建对象时,构造函数会为对象分配内存空间,并初始化类中所有实例成员;构造函数分为实例构造函数和静态构造函数
class Person { private string name; //实例构造函数 public Person() { name="小红"; } //静态构造函数用于初始化类中的静态成员,不能有访问修饰符,不能有参数且只会运行一次,在创建第一个实例或引用任何静态成员之前,CLR将自动调用静态构造函数 static Person(int a ) { } }
- 构造函数具有以下特点
- 构造函数可以进行方法重载
- 如果没有为类显式地定义一个构造函数,则C#编译器会自动生成一个函数为空的默认无参的实例构造函数
- 可以对实例构造函数指定访问级别,即可以使用
public
,protected
和private
修饰符来修饰.然而不是任何一个函数都可以成为实例构造函数,实例构造函数必须满足一下两个条件- 构造函数必须与类同名
- 构造函数不允许有返回值
析构函数
-
析构函数用于在类销毁之前释放类实例所使用的托管和非托管资源
- 析构函数定义
- 不能在结构体中定义析构函数,只能对类使用析构函数
- 一个类只能有一个析构函数
- 无法继承或重载析构函数
- 无法显式地调用析构函数,析构函数是由GC自动调用
- 析构函数无参,无修饰符
class Person { //析构函数 ~Person() { Console.WriteLine("析构函数被调用"); } }
- 析构函数定义
索引器
-
当一个类包含数组成员时,可以使用索引器简化对类中数组成员的访问.索引器定义类似于属性,有
get
与set
访问器.
-索引器定义[修饰符] 数据类型 this[索引类型 index] { get{//返回类中数组某个元素} set{//对类中数组元素赋值} }
//实例 class Program { static void Main(string[] args) { Person p = new Person(); //通过索引器给数组赋值 p[0] = 1; p[1] = 2; Console.WriteLine(p[0]); Console.WriteLine(p[1]); Console.ReadLine(); } } class Person { private int[] intarray = new int[10]; //索引器的定义 public int this[int index] { get { return intarray[index]; } set { intarray[index] = value; } } } //输出结果 分别为 1,2
类实例化
- 通过关键字
new
类名 实例化名=new 类名();
类与结构体的区别
- 定义类使用
class
关键字,结构体使用struct
关键字 - 结构体中不可对声明字段进行初始化,但类可以
- 如果没有为类显式地定义构造函数,C#编译器会自动生成一个无参数的实例构造函数(称之为隐式构造函数);为类显式地定义了一个构造函数,C#编译器将不会自动生成隐式的构造函数; 但结构体中,无论是否显式定义了构造函数,隐式构造函数都是一直存在的
- 结构体不能显式定义无参构造函数
- 结构体构造函数中,必须为结构体中所有字段赋值
- 创建结构体对象不可以使用
new
关键字,但此时结构体对象中的字段是没有初始值的;而类必须使用new
来创建对象 - 结构体不能继承结构或类,但可以实现接口;类可以继承类,当不能继承结构,也可以实现接口
- 类是引用类型,结构是值类型
- 结构体不能定义析构函数
- 不能使用
abstract
和sealed
关键字修饰结构体,而类可以