目录
一、C#程序结构
1、cs文件结构
2、编译并执行程序
二、C#基本语法
1、关键字
2、注释
3、标识符
4、关键字
三、C#数据类型
1、值类型
2、引用类型
3、指针类型
四、C#变量
1、声明变量
2、初始化变量
3、ReadLine()函数
五、C#数据类型转换
1、隐式类型转换
2、显式类型转换
六、C#运算符
1、算术运算符
2、关系运算符
3、逻辑运算符
4、位运算符
5、赋值运算符
6、其他运算符
七、C#运算符优先级
八、C#常量
1、定义常量
2、整数常量
3、浮点常量
4、字符常量
5、字符串常量
九、C#可空类型
1、Null 合并运算符(??)
下面简单介绍一下C#的程序结构,代码如下:
其中【using】关键字用于在程序中引入 System 命名空间。一个程序中一般有多个 using 语句。
其中【namespace】关键字用来声明一个命名空间。"MyFirstWinFormApp" 则是命名空间的名字,命名空间是类的集合,上面代码中名为 "MyFirstWinFormApp" 的命名空间中包含了一个名为 "Program" 的类。
其中【class】关键字用来定义一个类,"Program" 则是类名,类中通常用来存放程序中要使用的数据和函数(也叫方法)。
Main 为定义的函数名称,Main 函数是整个 C# 程序的入口,其中包含了程序运行时需要执行的操作。static 和 void 都是用来修饰 Main 函数的关键字。
※ 以下几点值得注意:
我们可以通过使用 Visual Studio 来编译和执行 C# 程序,除了可以使用 Visual Studio 来编译 C# 程序外,还可以直接使用命令行来编译 C# 程序。
在命令行工具中输入 csc helloworld.cs 命令,然后按回车键进行编译。如果代码中没有错误,那么则会在当前目录下生成一个名为 helloworld.exe 的可执行文件。
在命令行工具中输入生成文件的名字 helloworld 或 helloworld.exe 即可执行程序。也可以直接双击运行生成的 helloworld.exe 文件;
如果在使用 csc 命令时提示 "csc不是内部或外部命令...",则需要将如下路径的 .NET Framework 添加到系统环境变量中。
PATH:C:\Windows\Microsoft.NET\Framework\v4.0.30319
C# 是一种面向对象的编程语言。其概念和Java中的相关概念类似,因此不再赘述。下面以一个示例来说明:
首先,创建一个 Rectangle 对象,来表示长方形。该对象有两个属性length(长)和 width(宽),我们用一个方法来接收 length 和 width 属性的值,以此来计算这个长方形的面积。代码如下:
using System;
namespace MyFirstWinFormApp
{
class Rectangle
{
// 成员变量
public double length;
public double width;
public double GetArea(double length, double width)
{
this.length = length;
this.width = width;
return length * width;
}
static void Main()
{
Rectangle r = new Rectangle();
double area = r.GetArea(4.5, 1.5);
MessageBox.Show("Length:" + r.length);
MessageBox.Show("Width:" + r.width);
MessageBox.Show("Area:" + area);
}
}
}
关键字,是对编译器有特殊意义的预定义保留标识符,它们不能在程序中用作标识符。
(1)using 关键字
以 using 关键字开头的一行代码(如:using System;)可以称为一条 using 语句,几乎所有的 C# 程序都是以 using 语句开头的。using 语句主要用来引入程序中的命名空间,而且一个程序中可以包含多个 using 语句。
(2)class 关键字
class 关键字用来声明一个类,后面是类的名字,class 关键字与类名之间使用一个空格分隔。
注释用于对代码进行解释说明或注销暂时不需要的代码。在编译 C# 程序时编译器会忽略注释掉的内容。C# 中有3种注释方式:
(1)单行注释
单行注释使用 '//' 符号表示,如:
// 这是c#语言的单行注释方法.
(2)多行注释
多行注释以/*
开头,并以*/
结尾,/*
和*/
之间的所有内容都属于注释内容,如:
/*
* c#语言的多行注释语法.
*/
(3)文档注释
文档注释使用'///'来表示,如:
///
/// 应用程序的主入口点。
///
static void Main()
{
...
}
标识符是用来为类、变量、函数或任何其他自定义内容命名。C# 中标识符的定义规则如下所示:
A-Z、a-z
开头,后面可以跟英文字母A-Z、a-z
、数字0-9
或下划线_;? - + ! @ # % ^ & * ( ) [ ] { } . ; : " ' / \
,但是可以使用下划线_
; C# 中的关键字是编译器预先定义好的一些单词,也称为保留关键字或者保留标识符,这些关键字对编译器有着特殊的意义,不能用作标识符。如果非要使用,只需要在关键字前面加上@
前缀即可,例如@if
就是一个有效的标识符,而if
则是一个关键字。
此外,在 C# 中,有些关键字在代码的上下文中具有特殊的意义,例如 get 和 set,这样的关键字被称为上下文关键字。一般来说,C# 语言中新增的关键字都会作为上下文关键字,这样可以避免影响到使用旧版语言编写的 C# 程序。
C# 语言中内置了一些基本的数据类型。数据类型用来指定程序中变量可以存储的数据的类型,C# 中的数据类型可以大致分为三类:
C# 中的值类型是从 System.ValueType 类中派生出来的。对于值类型的变量我们可以直接为其分配一个具体的值。当声明一个值类型的变量时,系统会自动分配一块内存区域用来存储这个变量的值,需要注意的是,变量所占内存的大小会根据系统的不同而有所变化。
类型 | 举例 |
---|---|
整数类型 | byte(sbyte)、short(ushort)、int(uint)、long(ulong) |
浮点型 | float、double |
十进制类型 | decimal |
布尔类型 | bool |
字符类型 | string、char |
空类型 | null |
// 8 位无符号整数: 0 ~ 255(默认值:0)
byte b = 0;
// 16 位有符号整数类型: -32768 ~ 32767(默认值:0)
short s = 32767;
// 32 位有符号整数类型: -2147483648 ~ 2147483647(默认值:0)
int i = 0;
// 64 位有符号整数类型: -9223372036854775808 ~ 9223372036854775807(默认值:0L)
long l = 0;
// 32 位单精度浮点型: -3.4 * 10^38 ~ 3.4 * 10^38(默认值:0.0F)
// 注意:如果将一个小数赋值给一个变量,且不加任何后缀,系统会将其默认为double类型.
float f = 1.1F;
// 64 位双精度浮点型: (+/-)5.0 * 10^(-324) ~ (+/-)1.7 * 10^308(默认值:0.0D)
// double类型的数据范围包含了byte/short/int/long/float类型的数据范围!
double d = 1.1;
// 128 位精确的十进制值,具有 28~29 个有效位数: (-7.9 * 10^28 ~ 7.9 * 10^28) / (10^(0~28))
// 默认值:0.0M
// 注意:decimal是不能与float或double类型进行转换的.
// 浮点型之间的转换只有float转换为double一种!
decimal de = 1.1m;
de = 0;
// 布尔值:True 或 False(默认值:False)
bool b1 = true;
bool b2 = false;
MessageBox.Show(b1.ToString()); // True
MessageBox.Show(b2.ToString()); // False
// 字符串类型
string st = "Hello World!";
MessageBox.Show(st);
// 16 位 Unicode 字符:U +0000 到 U +ffff(默认值:'\0')
char c = 'H';
MessageBox.Show(c.ToString());
// 空类型
string str = "";
str = null;
如果想要获取类型或变量的确切大小,可以使用 sizeof 方法,如:
MessageBox.Show("int 类型的大小为:" + sizeof(int));
编译并执行上述代码,运行结果如下:
int 类型的大小为: 4
引用类型的变量中并不存储实际的数据值,而存储的是对数据(对象)的引用,换句话说就是,引用类型的变量中存储的是数据在内存中的地址。当多个变量都引用同一个内存地址时,如果其中一个变量改变了内存中数据的值,那么所有引用这个内存地址的变量的值都会改变。
C# 中内置的引用类型包括:Object(对象)、Dynamic(动态)和 string(字符串)。
(1)对象类型(Object)
对象类型是 C# 通用类型系统(Common Type System:CTS)中所有数据类型的最终基类,Object 是 System.Object 类的别名。任何类型的值都可以分配给对象类型,但是在分配值之前,需要对类型进行转换。
将值类型转换为对象类型的过程称为 "装箱",反之将对象类型转换为值类型的过程被称为 "拆箱"。注意,只有经过装箱的数据才能进行拆箱。
(2)动态类型(Dynamic)
你可以在动态类型的变量中存储任何类型的值,这些变量的类型检查是在程序运行时进行的。动态类型的声明语法,如下所示:
dynamic
= value; 如:
dynamic d = 20;
动态类型与对象类型类似,但对象类型变量的类型检查是在编译时进行的,而动态类型变量的类型检查则是在程序运行时进行的。
(3)字符串类型(String)
字符串类型的变量可以将一个字符串赋值给这个变量。字符串类型需要通过 String 类来创建,String 类是 System.String 类的别名,它是从对象类型中派生的。
在 C# 中有两种定义字符串类型的方式,分别是使用 "" 和 @"",如:
// 使用双引号的声明方式
String str = "http://c.biancheng.net/";// 使用@双引号的声明方式
string str = @"C:\Windows";备注:使用@双引号方式声明的字符串称为「逐字字符串」,逐字字符串会将转义字符「\」当作普通字符对待。如:
string str = @"C:\Windows";
等价于,
string str = "C:\\Windows";
。
另外,在 @"" 方式声明的字符串中可以任意使用换行。换行符及缩进空格等都会计算在字符串的长度之中。
C# 语言中的指针是一个变量,也称为定位器或指示符。它可以存储另一种类型的内存地址,C# 中的指针与 C 或 C++ 中的指针具有相同的功能。
指针类型的声明语法,如下所示:
type* identifier;
如:
char* cptr;
int* iptr;
变量可以理解为程序可以操作的内存区域的名称。在 C# 中每个变量都有自己特定的类型,这个类型确定了变量所占内存的大小、布局、取值范围以及可以对该变量执行的操作。
C# 中的基本变量类型可以归纳为以下几种:
(1)语法:
data_type variable_list;
说明:
data_type 为变量的类型,可以是 C# 中任何有效的数据类型,也可以是我们自定义的数据类型;
variable_list 为要声明的变量名称,variable_list 中可以包含多个变量名称,每个变量名之间使用逗号进行分隔(这样我们就可以同时定义多个变量);
C# 中变量的名称需要遵循如下所示的规则:
a-z, A-Z
、数字0-9
和下划线_
;a-z, A-Z
或下划线_
开头,不能以数字开头;C# 中变量可以通过等号后跟一个常量表达式的形式进行初始化(赋值),语法格式如下:
// 先声明后初始化(赋值)
data_type variable_name;
variable_name = value;
也可以在变量声明时并进行初始化,只需要在声明变量后使用等号后跟一个常量表达式即可,语法格式如下:
data_type variable_name = value;
举例如下:
int a, b, c;
a = 1;
b = 2;
c = 3;
char d = '';
float e = 3.14, f = 1.23;
该函数是由 System 命名空间中的 Console 类提供的,使用 ReadLine() 函数可以接收来自用户输入的内容并将其存储到变量中。代码如下:
int a, b;
Console.WriteLine("请输入第一个数字:");
a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入第二个数字:");
b = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("{0}+{1}={2}",a, b, a + b);
备注:Console.ReadLine() 接收的数据是字符串格式的,这里使用 Convert.ToInt32() 函数来将用户输入的数据转换为 int 类型。
数据类型转换就是将一种类型的数据转换为另一种类型。在 C# 中有两种形式的类型转换方式,分别是隐式类型转换和显示类型转换。
隐式类型转换是由 C# 以类型安全的方式执行的,转换的过程中不会导致数据丢失。例如从较小的整数类型(如:int)转换到较大的整数类型(如:long),从派生类转换为基类。
隐式类型转换不需要我们编写额外的代码,如:
int a = 10;
double b = a;
提示:
一种数据类型(类型 A),只要其取值范围完全包含在另一种数据类型(类型 B)的取值范围内,那么类型 A 就可以隐式转换为类型 B。
基于这一特性,C# 的隐式类型转换不会导致数据丢失。
显式类型转换也叫强制类型转换。这种转换需要使用(type)value的形式或者预定义函数显式的完成,显式转换需要用户明确的指定要转换的类型,而且在转换的过程中可能会造成数据丢失。例如,将 double 类型转换为 int 类型:
double d = 5673.74;
i = (int)d; // 转换前5673.74,转换后5673
C# 中还提供了一系列内置的类型转换方法,如下表所示:
方法 | 描述 | 方法 | 描述 |
ToBoolean | 将类型转换为布尔型 | ToInt64 | 将类型转换为 64 位整数类型 |
ToByte | 将类型转换为字节类型 | ToSbyte | 将类型转换为有符号字节类型 |
ToChar | 将类型转换为单个 Unicode 字符类型 | ToSingle | 将类型转换为小浮点数类型 |
ToDateTime | 将类型(整数或字符串类型)转换为日期时间的结构 | ToString | 将类型转换为字符串类型 |
ToDecimal | 将浮点型或整数类型转换为十进制类型 | ToType | 将类型转换为指定类型 |
ToDouble | 将类型转换为双精度浮点型 | ToUInt16 | 将类型转换为 16 位无符号整数类型 |
ToInt16 | 将类型转换为 16 位整数类型 | ToUInt32 | 将类型转换为 32 位无符号整数类型 |
ToInt32 | 将类型转换为 32 位整数类型 | ToUInt64 | 将类型转换为 64 位无符号整数类型 |
int i = 75;
float f = 53.005;
double d = 2345.7652;
bool b = true;
// 内置的类型转换方法
Console.WriteLine(i.ToString());
Console.WriteLine(f.ToString());
Console.WriteLine(d.ToString());
Console.WriteLine(b.ToString());
运算符其实就是一个符号,用来告诉编译器执行特定的数学或逻辑运算。C# 中内置了丰富的运算符,大致可以分为如下几类:
算术运算符即完成特定算术运算的符号。C# 中支持的算术运算符如下表所示:(假设变量 A = 1,变量 B = 2)
运算符 | 描述 | 示例 |
+ | 加法运算符,对运算符左右两边的操作数执行加法操作 | A + B 值为 3 |
- | 减法运算符,对运算符左右两边的操作数执行减法操作 | A - B 值为 -1 |
* | 乘法运算符,将运算符左右两边的操作数相乘 | A * B 值为 2 |
/ | 除法运算符,用运算符左边的操作数除以右边的操作数 | B / A 值为 2 |
% | 取模运算符,整除后的余数 | B % A 值为 0 |
++ | 自增运算符,整数值增加 1 | A++ 值为 2 |
-- | 自减运算符,整数值减少 1 | A-- 值为 0 |
注意:自增运算符和自减运算符,它们既可以放在变量的前面也可以放在变量的后面。在变量的前面时表示先进行自增或自减运算,然后再将值赋值给变量;在变量的后面时则正好相反,先将值赋给变量,然后再进行自增或自减运算。
关系运算符用来比较运算符左右两边的操作数。下表列举了 C# 中支持的所有关系运算符:(假设变量 A = 1,变量 B = 2)
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真 | (A == B) 不为真 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真 | (A != B) 为真 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真 | (A > B) 不为真 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真 | (A < B) 为真 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真 | (A >= B) 不为真 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真 | (A <= B) 为真 |
下表列举了 C# 中支持的逻辑运算符:(假设变量 A 的布尔值是 true,变量 B 的布尔值是 false)
运算符 | 描述 | 实例 |
---|---|---|
&& | 逻辑与运算符,如果两个操作数都为真,则结果为真 | (A && B) 为假 |
|| | 逻辑或运算符,如果两个操作数中有任意一个为真,则结果为真 | (A || B) 为真 |
! | 逻辑非运算符,用来对操作数的逻辑状态取反,如果结果为真,那么取反后则为假 | !(A && B) 为真 |
位运算符用来对二进制数进行位操作。下表列举了 C# 中支持的位运算符:
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与,对两个操作数的二进制位进行按位与运算,即当两个数对应的二进制位均为 1 时,结果位为 1,否则为 0 | (A & B) 将得到 12,即为 0000 1100 |
| | 按位或,对两个操作数的二进制位进行按位或运算,即当两个数对应的二进制位有一个为 1 时,结果就为 1,否则为 0 | (A | B) 将得到 61,即为 0011 1101 |
^ | 按位异或,对两个操作数的二进制位进行按位异或运算,即当两个数对应的二进制位不同时,结果为 1,否则为 0 | (A ^ B) 将得到 49,即为 0011 0001 |
~ | 按位取反,该运算符具有"翻转"位效果,即 0 变成 1,1 变成 0,包括符号位 | (~A ) 将得到 -61,即为 1100 0011 |
<< | 二进制左移运算符,左操作数的值向左移动右操作数指定的位数 | A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符,左操作数的值向右移动右操作数指定的位数 | A >> 2 将得到 15,即为 0000 1111 |
赋值运算符顾名思义就是用来为变量赋值的。下表列举了 C# 中支持的赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 最简单的赋值运算符,把右边操作数的值赋给左边的操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模并赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
C# 中还支持一些其他的重要运算符,如下表所示:
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回数据类型的大小 | sizeof(int),将返回 4 |
typeof() | 返回 class 的类型 | typeof(StreamReader) |
& | 返回变量的地址 | &a 将得到变量的实际地址 |
* | 变量的指针 | *a; 将指向一个变量。 |
? : | 三元(三目)运算符 | a>b ? X : Y; 如果条件为真,则值为 X : 否则值为 Y |
is | 判断对象是否为某一类型 | if( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象 |
as | 强制转换,即使转换失败也不会抛出异常。 | Object obj = new StringReader("Hello"); StringReader r = obj as StringReader; |
通过前面的学习我们知道运算符有不同的类型,当这些不同类型的运算符出现在同一个表达式中时,就必须遵循运算符的优先级来进行运算,才能保证运算的合理性和结果的正确性、唯一性。运算符的优先级决定了表达式中各个部分执行运算的先后顺序。
下表中详细介绍了 C# 中运算符的优先级顺序:
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
---|---|---|---|---|---|
1 | [] | 数组下标 | 数组名[整型表达式] | 左到右 | |
() | 圆括号 | (表达式)/函数名(形参表) | |||
. | 成员选择(对象) | 对象.成员名 | |||
-> | 成员选择(指针) | 对象指针->成员名 | |||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
(type) | 强制类型转换 | (数据类型)表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | 单目运算符 | ||
-- | 自减运算符 | --变量名/变量名-- | 单目运算符 | ||
* | 取值运算符 | *指针表达式 | 单目运算符 | ||
& | 取地址运算符 | &左值表达式 | 单目运算符 | ||
! | 逻辑非运算符 | !表达式 | 单目运算符 | ||
~ | 按位取反运算符 | ~表达式 | 单目运算符 | ||
sizeof | 长度运算符 | sizeof表达式/sizeof(类型) | |||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | 双目运算符 | ||
% | 余数(取模) | 整型表达式%整型表达式 | 双目运算符 | ||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | 双目运算符 | ||
5 | << | 左移 | 表达式<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 表达式>>表达式 | 双目运算符 | ||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | 双目运算符 | ||
< | 小于 | 表达式<表达式 | 双目运算符 | ||
<= | 小于等于 | 表达式<=表达式 | 双目运算符 | ||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!=表达式 | 双目运算符 | ||
8 | & | 按位与 | 整型表达式&整型表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 整型表达式^整型表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 整型表达式|整型表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1?表达式2:表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | |
/= | 除后赋值 | 变量/=表达式 | |||
*= | 乘后赋值 | 变量*=表达式 | |||
%= | 取模后赋值 | 变量%=表达式 | |||
+= | 加后赋值 | 变量+=表达式 | |||
-= | 减后赋值 | 变量-=表达式 | |||
<<= | 左移后赋值 | 变量<<=表达式 | |||
>>= | 右移后赋值 | 变量>>=表达式 | |||
&= | 按位与后赋值 | 变量&=表达式 | |||
^= | 按位异或后赋值 | 变量^=表达式 | |||
|= | 按位或后赋值 | 变量|=表达式 | |||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | 从左向右顺序运算 |
与前面介绍的变量类似,唯一不同的是常量的值在程序的编译阶段就已经确定了,而且在程序的运行期间不允许修改。常量可以是任何基本数据类型,如整数常量、浮点常量、字符串常量等等。
常量需要使用 const 关键字定义,语法格式如下所示:
const data_type constant_name = value;
说明:
data_type 为常量的数据类型;
constant_name 为常量名(类似于变量名);
value 为常量的值;
举例:
// 定义一个常量
const double pi = 3.14;
整数常量可以是八进制、十进制或者十六进制。可以使用前缀指定具体的进制,如:0x
或0X
表示十六进制,0
表示八进制,没有前缀则表示十进制。
除了前缀外,整数常量还可以包含后缀。后缀可以是 U 和 L 的组合,U 和 L 分别表示 unsigned 和 long。后缀既可以大写也可以小写,而且可以以任意顺序进行组合,但是不能重复。
下面列举了一些整数常量的示例:
85 // 合法:十进制常量
0213 // 合法:八进制常量
0x4b // 合法:十六进制常量
30 // 合法:int 类型常量
30u // 合法:无符号 int 类型常量
30l // 合法:long 类型常量
30ul // 合法:无符号 long 类型常量
068 // 非法:8 不是一个八进制数字
032UU // 非法:后缀不能重复
浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以用小数或指数形式来表示浮点常量。下面列举了一些浮点常量的示例:
3.14159 // 合法
314159E-5L // 合法
510E // 非法:不完全指数
210f // 非法:没有小数或指数
.e55 // 非法:缺少整数或小数
注意:当使用小数形式表示浮点常量时,必须包含小数点、指数或同时包含两者。当使用指数形式表示浮点常量时,必须包括整数部分、小数部分或同时包含两者。有符号的指数使用 e 或 E 表示。
字符常量需要使用单引号引起来,类似于定义字符串类型的变量,例如'x'
。一个字符常量可以是一个普通字符(例如'x'
)、转义序列(例如'\t'
)或 Unicode 字符(例如'\u02C0'
)。
在 C# 中,有些字符前面带有一个反斜杠,这样的字符具有特殊含义。例如\n
用于表示换行符、\t
表示制表符。下表中列举了一些常用的转义字符:
转义序列 | 含义 | 转义序列 | 含义 |
---|---|---|---|
\\ | \ 字符 | \f |
换页符(Form feed) |
\' | ' 字符 | \n | 换行符(Newline) |
\" | " 字符 | \r | 回车 |
\? | ? 字符 | \t | 水平制表符 tab |
\a | Alert 或 bell | \v | 垂直制表符 tab |
\b | 退格键(Backspace) | \ooo | 一到三位的八进制字符 |
\xhh . . . | 一个或多个数字的十六进制字符 |
字符串常量需要使用双引号""
或@""
引起来。字符串常量与字符常量相似,可以是纯字符、转义序列或 Unicode 字符。下面列举了一些字符串常量。
"helloworld";
@"helloworld";
"hello \t world"; // hello world
@"hello \t world"; // hello \t world
@"hello
world";
在 C# 1.x 的版本中,一个值类型的变量是不可以被赋值为 null(空值)的,否则会产生异常。在 C# 2.0 中,新增了一个 nullable 类型,我们可以使用 nullable 类型定义包含 null 值的数据。声明可空类型的语法如下:
data_type? variable_name = null;
说明:
data_type 为要声明的数据类型,后面紧跟一个问号;
variable_name 则为变量的名称;
举例:
// 可空类型的用法:
int? num1;
num1 = null;
int? num2 = 123;
double? num3 = new double?();
double? num4 = 3.1415926;
bool? boolval = null;
// 输出这些值
Console.WriteLine("num1 = {0} \r\n num2 = {1} \r\n num3 = {2} \r\n num4 = {3} \r\n boolval = {4}", num1, num2, num3, num4, boolval);
Console.ReadLine();
// 运行结果如下:
num1 =
num2 = 123
num3 =
num4 = 3.1415926
boolval =
在 C# 中 Null 合并运算符(??)用于定义可空类型和引用类型的默认值。如果此运算符的左操作数不为 null,那么运算符将返回左操作数,否则返回右操作数。
需要注意的是,Null 合并运算符左右两边操作数的数据类型必须相同,或者右操作数的类型可以隐式的转换为左操作数的类型,否则将编译错误。
// Null 合并运算符的使用:
int? num1 = null;
int? num2 = 123;
int num3;
num3 = num1 ?? 321;
Console.WriteLine("num3 = {0}", num3);
num3 = num2 ?? 321;
Console.WriteLine("num3 = {0}", num3);
Console.ReadLine();
// 运行结果如下:
num3 = 321
num3 = 123