一、C# 专栏
由于博主原先是做的Linux C/C++ 嵌入式领域,因此对 C# 也较为懵懂,C# 是典型的 OOP 编程,这一点与 C++ 类似,但是在语法上,C# 移除了对指针的运用以及内存管理,所以既不用考虑指针的复杂运用也不用考虑堆栈内存的手动释放。
现在出于工作需要,不得不学习 C# 语言,但这块内容的资料我认为是比较有限的,无论是某站,还是二手书,对于深入的内容讲得是非常少的,在编程的时候,即便是按需查询也是相当耗费时间以及很难第一时间全部掌握的,所以开辟此专栏也是为了记录在学习过程中的涉及到的深入知识点。
但为了将一些零碎的知识便于补充,还是在本章中,添加对 C# 基础知识的记录。
二、C# 基础知识
1、C# 标准输入输出函数
Console 类表示控制台应用程序的标准输入流、输出流和错误流。
Console 类中与输入/输出相关的方法如表所示:
|-------------|---------------------------------------|
| 方法 | 说明 |
| Read() | 从标准输入流读取下一个字符,返回 int 类型,只能记录 int 类型数据 |
| ReadLine() | 从标准输入流读取下一行字符,返回值为 string 类型 |
| Write() | 将指定的值写入标准输出流,输出后不换行 |
| WriteLine() | 将当前行终止符写入标准输出流,输出后换行 |
2、C# 数据类型(补充)
1、变量
C# 中的变量类型根据其定义可以分为两种:一种是值类型,另一种是引用类型。值类型变量直接存储其数据值,主要包含整数类型、浮点类型以及布尔类型等,值类型变量在栈中进行分配;引用类型是构建 C# 应用程序的主要对象类型数据,在应用程序执行的过程中,预先定义的对象类型以 new 创建对象实例,并且存储在堆栈中。
1.1)值类型和引用类型
值类型变量直接存储其数据值,主要包含整数类型、浮点类型以及布尔类型等。值类型变量在堆栈中进行分配。当以值类型作函数参数传递时,在函数内部改变形参的值,都不会改变实参原本的值。
引用类型是构建 C# 应用程序的主要对象类型数据,引用类型必须使用 new 关键字来创建引用类型变量。当以引用类型作函数参数传递时,需要用到 ref 关键字,此时在函数内部改变形参的值,会改变实参原本的值。
1.2)装箱和拆箱
将值类型转换为引用类型称为装箱,反之,将引用类型转换为值类型称为拆箱。
1.3)单精度浮点型
单精度浮点型 float 的小数精确到第7位,但是 C# 默认小数为 double 型,因此,在需要使用 float 型数据时,需要在数值后面加上 f 或者 F 来强制其值为 float 类型。
1.4)金钱类型 decimal
用来存储小数点超过16位(double)的数据类型:
decimal a = 2000m;
数据后面必须加一个 m 以区分数据类型,大小写均可以。
2、整数类型
与 C++ 不同的是,C# 中有两个额外的整数类型:sbyte 表示8位有符号整数,取值范围为:-128~127 以及 byte 表示8位无符号整数,取值范围为:0~255。
其余与 C++ 类似,只是无符号 unsigned 缩写为"u",例如:uint、ushort等。
3、C# 类访问权限
1、类访问权限与 C++ 的区别
C++中通过 public: 和 private: 的语法批量声明成员的访问权限,但 C# 要求每个成员单独指定访问修饰符。因此不用添加冒号,而且,默认访问权限是 private 私有的。
例如有:
cs
class Person
{
public void func(int a)
{
m_A = a;
Console.WriteLine("这是一个C#代码函数打印 m_A = "+ m_A);
Console.ReadKey();
}
private int m_A;
};
C# 的类必须属于命名空间,没有全局作用域的类定义。
2、类对象的创建与 C++ 的区别
类的创建不能简单的只创建类对象,而是应当用 new 的关键字方式创建。
3、类访问修饰符(访问权限)
C# 中的访问修饰符主要包括 private、protected、internal、protected internal 和 public。主要区别如下表所示:
|--------------------|-----------|--------------|
| 访问修饰符 | 应用范围 | 访问范围 |
| private | 所有类或者成员 | 只能在本类中访问 |
| protected | 类和内嵌的所有成员 | 在本类和其子类中访问 |
| internal | 类和内嵌的所有成员 | 在同一程序集中访问 |
| protected internal | 类和内嵌的所有成员 | 在同一程序集和子类中访问 |
| public | 所有类或者成员 | 任何程序都可以访问 |
需要注意的是,在定义类时,只能使用 public 或者 internal,这取决于是否希望在包含类的程序集外部访问它。
正常情况下不能把类定义为 private、protected 或者 protected internal 类型,但是可以使用它们定义嵌套的内部类(也就是在一个类中再声明一个类),则内部类总是可以访问外部的所有成员。
4、C# 数组
1、与 C/C++ 的区别
在 C/C++ 中声明一个数组时,中括号在数组名字的后面;而在 C# 中声明一个数组时,中括号在数组元素类型的后面。
在 C# 中,声明数组后,还不能访问它的任何元素,因为声明数组只给出了数组名和元素的数据类型,要真正使用数组,还需要为它分配内存空间,在为数组分配内存空间时,必须指明数组的长度,为数组分配内存空间的语法格式如下:
数组名称 = new 数组元素类型[数组元素的个数]
也可以在声明的同时为数组分配内存空间:
数组元素类型[] 数组名称 = new 数组元素类型[数组元素的个数]
2、一维数组的声明和使用
一维数组的声明语法格式如下:
type[] arrayName; //数组元素类型[] 数组名字
一维数组的使用例如有:
cs
int[] arr1;
arr1 = new int[10];
int[] arr2 = new int[10];
int[] arr3 = new int[10]{1,2,3,4,5,6,7,8,9,10};
int[] arr4 = {1,2,3,4,5,6,7,8,9,10};
可以使用 length 属性来获取数组的长度:arr1.length。
3、二维数组的声明和使用
二维数组的声明语法格式如下:
type[ , ] arrayName;
type[][] arrayName;
二维数组的使用例如有:
cs
int[,] a = new int[2,4]; //定义一个两行四列的 int 类型的二维数组
int[][] b = new int[2][];
b[0] = new int[2];
b[1] = new int[3]; //不规则的二维数组
int[,] c = new int[,]{{1,2},{3,4}};
4、动态二维数组的声明和使用
动态二维数组的声明语法格式如下:
type[] arrayName;
arrayName = new type[n1, n2, n3,,,,,,]
动态二维数组的使用例如有:
cs
int m = 2;
int n = 2;
int[,] a = new int[m,n]; // m 和 n 可以是任意值
5、C# 字符与字符串
C# 的字符类 char 的使用和字符串类 string 的使用与 C++ 类似,不同的是 C# 的字符串类中封装了一些方法,这可以后续介绍。
6、C# 类
1、类的声明
C# 中,类是使用 class 关键字来声明的,语法如下:
cs
类修饰符 class 类名
{}
2、构造函数和析构函数
C# 中的构造函数与析构函数同 C++ 类似,可以参考 C++ 中对象和类的类的构造函数和析构函数。
2.1)私有构造函数
与 C++ 不同的是,在定义构造函数时,也可以使用 private 进行修饰,用于表示构造函数只能在本类中访问,在其它类中不能访问,但是,如果类中只定义了私有构造函数,将导致类不能使用 new 运算符在外部代码中实例化。
然而,可以通过编写一个公共的静态属性或者方法来解决这个问题,例如有:
cs
class Person
{
private Person()
{
//私有构造函数
}
public static Person newPerson
{
return new Person();
}
static void Main(string[] args)
{
Person p = new Person.newPerson();
}
}
使用私有构造函数可以实现一种常见的设计模式------单例模式,即同一类创建的所有对象都是同一个实例。
2.2)静态构造函数
在 C# 中,可以为类定义静态构造函数,这种构造函数只执行一次,编写静态构造函数的主要原因是类有一些静态字段或属性,需要在第一次使用类之前从外部源中初始化这些静态字段和属性。
在定义静态构造函数时,不能设置访问修饰符,因为其他 C# 代码从来不会调用它,它只在引用类之前执行一次,另外,静态构造函数不能带任何参数,而且一个类中只能有一个静态构造函数,它只能访问类的静态成员,不能访问实例成员。
例如有:
cs
namespace _4._3
{
internal class Program
{
static Program()
{
Console.WriteLine("静态构造函数的调用");
}
private Program()
{
Console.WriteLine("私有构造函数的调用");
}
static void Main(string[] args)
{
Program p1 = new Program();
Program p2 = new Program();
Program p3 = new Program();
Console.ReadLine();
}
}