C#语法笔记(一)

本文详细介绍了C#中的变量命名规则、数据类型(包括值类型和引用类型)、装箱拆箱、输入输出操作、可空类型、类型转换、关系和类型测试运算符、逻辑运算符、字符串操作、位运算以及控制流程(如循环和异常处理)。此外,还涵盖了数组、指针的使用、类和对象的概念、访问修饰符、方法、事件、静态成员与实例成员、结构和枚举以及泛型的应用。文章深入浅出地阐述了C#语法的基础知识,适合初学者阅读。
摘要由CSDN通过智能技术生成

C#中变量的命名:

在C#中,标识符是区分大小写的。推荐的命名约定建议如下:

对于变量名和参数名,使用Camel大小写规则,该规则要求除了第一个单词外,其他单词的首字母大写,如bookTitle;

对于方法名和其他标识符,使用Pascal大小写规则,该规则要求每个单词的首字母都大写,如GetBookTitle;


C#数据类型:

1、值类型

(1)简单类型,如int  double  char 

(2)枚举类型,enum E

(3)结构类型,struct  S

(4)可以为null的类型,其他所有具有null值的类型的扩展

2、引用类型

(1)类类型

A、其他所有类型的最终基类,object

        B、Unicode字符串类型 string

        C、class  C形式的用户自定义类型

(2)接口类型  Interface

(3)数组类型  一维数组和多维数组

(4)委托类型  delegate  int  D


实现值类型和引用类型之间的转换: 装箱和拆箱

装箱:将一个值类型数据隐式或显示转换为object类型数据,或者把这个值类型转换成一个被该值类型应用的接口类型。

拆箱:将一个对象类型显示转换成一个值类型,或将一个接口类型显示的转换成可执行该接口的值类型。


C#数据的输入输出(在Console程序中),使用函数Console.ReadLine(), Console.WriteLine()等。

int  a = Convert.ToInt32(Console.ReadLine());  //将console输入的字符串,转换为int32形式

Console.WriteLine(a + "hello"); //将a转换为字符串,同时加上另一个字符串,输出


可以为null的类型:  T?

可以为null的类型表示可赋值为null值的类型变量,其取值范围为其基础值类型正常范围内加一个null值。如bool? (Nulllable<bool>  )的值包括true,  false,  null。

可以为null类型的赋值, int?  A = 10


类型转换:

隐式转换、显式转换、Convert.Toxx函数


在C#代码中,如果在未检查的上下文中执行,整型间的显式数字转换或算术运算可能造成溢出,从而导致错误。使用checked关键字进行类型检验。

int  j = checked(i + 1);  //检测是否会溢出

可以在编译器中设置/checked 或/unchecked 进行全局检验。


关系和类型测试运算符

==, >=, <= , >, <, != 等传统的比较运算符, x is T,  x  as  T

(1)关系运算符的优先级相同;

(2)对于两个预定义的数值类型,关系运算符按照操作数的大小进行比较

(3)对于string类型,关系运算符比较字符串的值,即按照ascii从左到右一一比较,直到出现不同的字符,进行比较大小。

(4)对于string类型之外的引用类型,如果两个操作数引用同一个对象,则==返回相等;否则返回  !=

(5)int和System.Int32是相同的数据类型。

x  is  T: 判断数据x是否属于类型T

x  as  T: 尝试将x转换为类型T, 如果成功,返回转换为T类型的x, 否则返回null.


逻辑运算符

!,  &,  | , ^, &&, || 

! 逻辑非, & 逻辑与, | 逻辑或

&& 短路与:  A&&B 如果A 为false,则不必计算B 的布尔值,直接判定为false

|| 短路或:   A || B, 如果A 为 true, 则不必计算B的布尔值,直接判定为true


字符串运算符

字符串运算符只有一个  +, 表示将两个字符串连接,当其中一个操作数是字符串类型或两个操作数都是字符串类型时,则+ 运算符执行字符串连接操作。


位运算

~  按位求补,  <<  操作数左移, >> 操作数右移, & 按位逻辑与, | 按位逻辑或, ^ 按位逻辑异或

(1)按位求补运算~ 是为 int、uint、long和ulong类型预定义的,对操作数执行求补操作,其效果相当于反转每一位。

(2)左右移操作符的第二个操作数必须为int 类型


程序for循环结构

可以使用foreach 进行循环操作;

foreach( 类型名称   变量名称  in  数组或集合名称)

{   操作}


异常处理

try{  尝试执行可能触发异常的代码段 }    

catch( xxException e)

{  在异常发生时执行的代码}

finally{ 最终必须执行的代码(即时发生异常), 如释放资源等}


数组和指针

C#中数组的属性;

(1)数组使用类型声明,通过数组下标(或索引)来访问数组中的数据元素

(2)数组可以是一维数组、多维数组或交错数组

(3)数组元素可以为任意类型,包括数组类型

(4)数组下标(索引)从0开始

(5)数组元素的默认值为0, 引用类型的默认值为null

(6)交错数组是数组的数组,因此它的元素是引用类型,默认值为null

(7)数组中的元素总数是数组中各维度长度的乘积

(8)通过.NET框架中的System.Array类来支持数组。因此,可以利用该类的属性和方法来操作数组

使用数组时需要注意;

(1)数组必须先声明,因为数组为引用类型,数组变量的声明只是为数组实例的引用留出空间。

   声明一维数组:int [] A;

(2)数组在声明后必须实例化才能使用。数组实例在运行时使用new 运算符动态创建,new运算符指定新数组实例的长度,new运算符自动将数组的元素初始化为相应的默认值。

(3)初始化例子:int []A = new int[3]{1, 3, 5} ,简化为   int [] A = {1, 3, 5}; 一维数组,含有三个元素,

一旦要为数组指定初始化值,就必须为数组的所有元素指定初始化值,指定值的个数必须严格等于数组的长度。

一维数组: int [] A;  A = new  int[4];    int []A = new int[3]{1, 3, 5} ,简化为   int [] A = {1, 3, 5}; 

多维数组 : int [ , ]  A = new int[4, 3];   int [ , ,] B = new int[3, 5, 2] //三维数组 

int [, ]array = new int[2, 2]{ {1, 2},  {3, 4}};                int [, ]array = new int[ , ] { {1, 2}, {3, 4}};    int [ , ] array = { {1, 2}, {3, 4}}

交错数组:   交错数组是元素为数组的数组,数组的数组。交错数组的元素的维度和大小可以不同,交错数组同样需要声明、实例化并且初始化后才能使用。

int [][] A = new int[3][];  A[0] = new int[5];   A[1] = new int[3];   A[2]  = new  int[4];

int [][] A = new int[] [] 

{  new int[]{1, 2, 3},  new int[]{5, 3, 2},  new int[] {3, 2}}

例:混合使用多维数组和交错数组 int [] [ , ] A =  new int[3] [ , ] { new int[ , ]{ {1, 2}, {2, 3}},  new int [ , ]{ {1, 1}, {2, 2}},  new int [ , ] { { 3, 4}, {5,6}}}

作为对象的数组::

C#中,数组实际上是对象,数组类型是从Array类派生而来的引用类型。 Array类是所有数组类型的抽象基类型。System.Array类提供了许多方法和属性,可用户数组的复制、排序等操作处理。如Clear(),  Clone(), CopyTo(), Copy() , GetLength()等


为了保证类型安全,默认情况下,C#不支持指针,从而避免了程序的复杂性。但在某些情况下,可能需要通过指针调用操作系统API函数、访问内存映射设备,或实现一些以时间为关键的算法。C#中使用unsafe关键字,可以定义不安全上下文,然后在不安全上下文中使用指针。

在公共语言运行时(CLR)中,不安全代码是无法验证的代码,其安全性无法由CLR进行 验证,使用不安全代码可能会引起安全风险和稳定性风险,程序员必须确保代码不会引起安全风险或指针错误。  CLR只对在完全受信任的程序集中的不安全代码执行操作,在C#中,为了编译不安全代码,必须使用/unsafe 编译应用程序。 可以将一个类、一个方法、代码块或字段标记为 unsafe, 如 

public unsafe void A()

int *  p: p是指向整数的指针;  int **p:p是指向整数的指针的指针;  int * [] p p是指向整数的指针的一维数组 ,但没有指向数组的指针。

(1)指针不能指向对象引用或会包含引用的结构,因为即使有指针指向对象引用,gia对象引用也可能会被执行垃圾回收,从而造成指针指向的内存空间包含的数据类型无效。

(2)void *类型表示指向未知类型的指针。因为目标类型是未知的,所以不能对void*类型的指针应用间接寻址运算符*, 也不能对这样的指针执行任何算术运算。但是void* 类型可以强制转化为其他任何类型的指针,反之亦然。

(3)指针可以为null,值为null 的指针表示指针没有指向有效的内存地址,针对null指针的操作将会出现异常。

(4)指针类型是单独的类型,与值类型或引用类型不同,指针类型不从object继承,而且不存在指针类型和object之间的转换。具体而言,指针不支持装箱和拆箱操作,但是允许不同指针类型之间以及指针和整型之间进行转换。

(5)指针分配内存,使用stackalloc。 stackalloc关键字用于不安全的代码上下文中,以便在堆栈上分配内存块 int *fib = stackalloc   int[100];

(6)关于fixed语句。

a) fixed语句只能出现在不安全的上下文中。

b)fixed语句禁止垃圾回收器重定位可移动的变量

c)fixed语句还可用于创建固定大小的缓冲区

d)fixed语句设置指向托管变量的指针并在statement执行期间钉住该变量。如果没有fixed语句,则指向可移动托管变量的指针的作用很小,因为垃圾回收可能不可预知的重定位变量,C#编译器值允许在fixed语句中分配指向托管变量的指针

e)无法修改在fixed语句中初始化的指针。


类和对象

类是C#语言的核心,C#中的一切类型都是类,所有的语句必须在类内。.NETFramework类库包含大量解决通用问题的类,一般可以通过创建自定义类和使用.NETFramework类库来解决实际问题。

创建对象:使用new运算符创建类的实例,该运算符为新的实例分配内存,调用构造函数初始化该实例,并返回对该实例的引用。类名    对象名    =  new   类名([参数表])

对象使用:类的对象使用 ”."操作符来引用类的成员。引用时,必须符合权限。

对象比较:用new创建一个类的对象时,将在托管堆中为对象分配一块内存,每一个对象都有不同的内存。代表对象的变量存储的是存放对象内存的地址。因此两个不同的对象,即时他们的所有成员的值或代码都相同,他们也是不相等的。但是,如果将一个对象赋值给另一个对象,则他们的变量都将保存同一块内存的地址,即两个对象是相同的。如果改变其中一个对象的状态(成员的值),那么也会影响另一个对象。

访问修饰符

1)public: 访问不受限制

2)protected:访问仅限于此类或从此类派生的类

3)internal:访问仅限于此程序(类所在的程序,即同一个编译单元,dll或exe中)

4)protected internal:protected或者internal,即访问仅限于此程序或从此类派生的类。

5)private:访问仅限于此类

当没有定义访问修饰符时,类成员默认访问修饰符为internal,即此类只能被定义它的程序使用。

嵌套类:

类的定义是可以嵌套的,在内部定义其他的类,类内声明的类称为内部类或者嵌套类。在编译单元或命名空间内声明的类成为顶级类,也成为包含类或者非嵌套类。嵌套类型默认为private。嵌套类也可以设置为public,internal等。

在理想情况下,嵌套类型仅由其包含类型进行实例化和使用。如果需要在其他类型中使用该嵌套类型,则建议定义单独的顶级类,避免使用嵌套类。

如果类A是类B的内部类,当需要在内部类A的内部访问类B的实例成员时,可以在类B中将代表类B的实例的this指针作为一个参数传递给内部类A的构造函数。这样类B中含有成员类A, 同时类A中保存类B的引用。

嵌套类的访问:内部类可以访问包含它的那个类可访问的所有成员,包括该类自己的具有private和protected声明的可访问性成员。这样内部类对象中可以new一个外部类对象,但实例化之后,该外部类对象和该内部类对象所属的外部类对象不是同一个。

分部类:

分部类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值