C# 语言类型
注释
//单行注释
/// <summary>
/// 方法注释
/// </summary>
/// <param name="args">方法参数</param>
/*
多行注释
*/
一.预定义类型
预定义类型又称框架类型,它们都在 System 命名空间下。
预定义类型又可以细分为 值类型 ,和 引用类型
(1) 值类型
值类型包含 所有的数值类型、char类型、bool类型、自定义的 struct 类型 和 enum 类型。
(2) 引用类型
引用类型包含 所有的类、数组、委托 和 接口类型 以及 预定义类型中的 string类型。
值类型:
- 数值
- 有符号整数(sbyte,short,int,long)
- 无符号整数(byte,ushort,uint,ulong)
- 实数(float,double,decimal)
- 逻辑值(bool)
- 字符(char)
引用类型:
- 字符串(string)
- 对象(object)
值类型大小
namespace TopSet06
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("-------字节型-------");
Console.WriteLine("有符号 sbyte is: "+ sizeof(sbyte));
Console.WriteLine("无符号 byte is: " + sizeof(byte));
Console.WriteLine("-------短整型-------");
Console.WriteLine("有符号 short is: " + sizeof(short));
Console.WriteLine("无符号 ushort is: " + sizeof(ushort));
Console.WriteLine("-------整型-------");
Console.WriteLine("有符号int is: " + sizeof(int));
Console.WriteLine("无符号uint is: " + sizeof(uint));
Console.WriteLine("-------长整型-------");
Console.WriteLine("long is: " + sizeof(long));
Console.WriteLine("ulong is: " + sizeof(ulong));
Console.WriteLine("-------浮点型-------");
Console.WriteLine("float is: " + sizeof(float));
Console.WriteLine("double is: " + sizeof(double));
Console.WriteLine("-------十进制小数-------");
Console.WriteLine("decimal is: " + sizeof(decimal));
Console.WriteLine("-------布尔型-------");
Console.WriteLine("bool is: " + sizeof(bool));
Console.WriteLine("-------字符型-------");
Console.WriteLine("char is: " + sizeof(char));
Console.ReadLine();
}
}
}
--输出
-------字节型-------
有符号 sbyte is: 1
无符号 byte is: 1
-------短整型-------
有符号 short is: 2
无符号 ushort is: 2
-------整型-------
有符号int is: 4
无符号uint is: 4
-------长整型-------
long is: 8
ulong is: 8
-------浮点型-------
float is: 4
double is: 8
-------十进制小数-------
decimal is: 16
-------布尔型-------
bool is: 1
-------字符型-------
char is: 2
1. 数值类型
1.1数值类型字面量表示
数值类型字面量有一些表示特性,简化程序员工作
namespace TopSet07
{
internal class Program
{
static void Main(string[] args)
{
int a = 0x560;
//需要C#7.0以上
int b = 0b00101010;
//需要C#7.0以上,并且vs版本需要2022 17.9以上
int c = 1_000_000_1_20;
double d = 1e10;
double D = 1E10;
double e = 1.5;
//float 类型需要添加末尾的f 或 F 大小写都行
float f = 1.5f;
//float 类型需要添加末尾的m 或 M 大小写都行
decimal g = 3.1415m;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Console.WriteLine(D);
Console.WriteLine(e);
Console.WriteLine(f);
Console.WriteLine(g);
Console.ReadLine();
}
}
}
--输出
1376
42
1000000120
10000000000
10000000000
1.5
1.5
3.1415
1.2 获取某个值的类型
namespace TopSet08
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine(10.0.GetType());
int a = 12;
Console.WriteLine(a.GetType());
Console.ReadLine();
}
}
}
--输出
System.Double
System.Int32
1.3 float 和 double 类型的特殊值
Console.WriteLine("------float------");
Console.WriteLine(float.PositiveInfinity);
Console.WriteLine(float.NegativeInfinity);
Console.WriteLine(float.Epsilon);
Console.WriteLine(float.MaxValue);
Console.WriteLine(float.MinValue);
Console.WriteLine(float.NaN);
Console.WriteLine("------double------");
Console.WriteLine(double.PositiveInfinity);
Console.WriteLine(double.NegativeInfinity);
Console.WriteLine(double.Epsilon);
Console.WriteLine(double.MaxValue);
Console.WriteLine(double.MinValue);
Console.WriteLine(double.NaN);
//NaN不等于任何数,包括NaN
//要判断是不是NaN ,只能用方法 IsNaN 来判断
Console.WriteLine("------IsNaN------");
Console.WriteLine(float.NaN == double.NaN); //false
Console.WriteLine(float.IsNaN(float.NaN)); //true
Console.ReadLine();
--输出
------float------
∞
-∞
1E-45
3.4028235E+38
-3.4028235E+38
NaN
------double------
∞
-∞
5E-324
1.7976931348623157E+308
-1.7976931348623157E+308
NaN
------IsNaN------
False
True
2. 算术运算
加减乘除取余
自加自减,案例略。
checked 和 unchecked 运算符
checked
checked 运算符可以检查算术是否溢出,在checked中溢出会报错。
浮点类型的无法使用该检查,因为浮点溢出会变为无穷值。
int a = 1_000_000;
int c = checked(a * a);
--输出报错
Unhandled exception. System.OverflowException: Arithmetic operation resulted in an overflow.
at
unchecked
不管里面是否溢出都不管,溢出了也不报错
int a = 1_000_000;
int b = unchecked( a*a);
Console.WriteLine(b);
--输出
-727379968
3. 位运算符
左移<< , 右移 >> , 异或 ^ , 按位或 | , 按位与 & , 按位取反 ~
4. 比较运算和条件运算
比较运算:>= , <= ,== , != , > , <
条件运算: ||,&& , w? a:b
二.字符串和字符类型简述
(1) 字符类型基本用法
字符类型表示一个Unicode字符或者一个转义字符,占用两个字节,字符类型可以直接转换成short类型,转成其他类型需要显示转换。
char a = 'A';
char a = '\n';
(2) 字符串类型基本用法
字符串类型是引用类型,但是却遵循 == 运算时是进行值的比较,字符串类型无法使用 > < ,只能使用CompareTo方法
string a = "hello";
string b = "nihao";
string c = "hello";
int v = a.CompareTo(b);
Console.WriteLine(a==c);
Console.WriteLine(v);
Console.ReadLine();
--输出
True
-1
@符号
string类型中,可以使用@表示内部不支持转义字符,所有的字符就是字符,没有别的意思。
注意 @符号因为还需要左右"" 两个引号把字符串框起来,所以在它们内部如果想输出双引号,那么需要两个双引号来表示一个双引号
string a = "\n\n"; //输出两个换行
string b = @"\n\n"; //输出字符 \n\n
//两个双引号
string c = @"{name=""xiaoli""}" //输出 {name="xiaoli"}
$ 符号
字符串插值,C#6.0版本以上才有,使用插值的使用,还可以使用冒号进行插值的格式化,略。
int a = 10;
string b = $"num is {a}";
Console.WriteLine(b);
--输出
num is 10
$ 和 @ 结合使用
结合使用可以让插值字符串换行,但是必须 $ 在 @ 前面
int a = 10;
string b = $@"num is {
a}, hhhhhh";
Console.WriteLine(b);
--输出
num is 10, hhhhhh
连接字符串
直接使用 + 加号可以直接连接字符串,但是,更好的解决方案是StringBuilder类型,如果需要频繁大量的连接字符串,那么请使用StringBuilder
string a = "abc"+"d";
StringBuilder sb = new StringBuilder();
sb.Append("aa");
Console.WriteLine(sb.ToString()); //输出 aa
三、数组
1. 数组创建
//第一种 数组的初始化方式
//int[] scores = {23,43,432,42,34,234,234,2,34} ;//使用这种方式赋值的时候,一定要注意 在数组声明的时候赋值
//第二种数组创建的方式
//int[] scores = new int[10];
//int[] scores;
//scores = new int[10];
//int[] scores = new int[10]{3,43,43,242,342,4,234,34,234,5};
//Console.WriteLine(scores[10]);//当我们访问一个索引不存在的值的时候,会出现异常exception
//char[] charArray = new char[2]{'a','b'};
//Console.WriteLine(charArray[1]);
string[] names = new string[]{
"taikr","baidu","google","apple"};
Console.WriteLine(names[0]);
Console.ReadKey();
2. 多维数组
多维数组分为锯齿形数组和矩形数组
2.1 矩形数组
//矩形数组
//1.
int[,] retrict = new int[3, 3]
{
{
1,2,3},
{
2,3,4},
{
2,3,4}
};
//2.
int[,] rer =
{
{
1,2,6},
{
2,3,4},
{
2,3,4}
};
2.2 锯齿形数组
//锯齿形数组
//1.
int[][] res = new int[3][];
res[0] = new int[] {
4, 5 };
res[1] = new int[] {
4, 5 };
res[2] = new int[] {
4, 5 };
//2.
int[][] tes = new int[][]
{
new int[]{
4,5},
new int[]{
1},
new int[]{
7,8,9}
};
//3.
int[][] ret =
{
new int[] {
4, 5 },
new int[] {
4, 5 },
};
四、枚举类型和结构体
1. 枚举类型使用
namespace _037_枚举类型 {
//枚举类型的定义
enum GameState:byte//修改该枚举类型的存储类型,默认为int
{
Pause = 100, // 默认代表的是整数0
Failed = 101,// 默认代表的是整数1
Success=102,// 默认代表的是整数2
Start=200// 默认代表的是整数3
}
class Program
{
static void Main(string[] args) {
////利用定义好的枚举类型 去声明变量
//GameState state = GameState.Start;
//if (state == GameState.Start)//枚举类型比较
//{
// Console.WriteLine("当前处于游戏开始状态");
//}
//Console.WriteLine(state);
//int state =3;
//if (state == 3)
//{
// Console.WriteLine("当前处于游戏开始界面");
//}
GameState state = GameState.Start;
int num = (int)state;
Console.WriteLine(num);
Console.ReadKey();
}
}
}
2. 结构体的使用
namespace _038_结构体 {
//我们可以把结构体当成,几个类型组成了一个新的类型
//比如下面的这个就是使用了3个float类型的变量,来表示一个坐标类型
struct Position
{
public float x;
public float y;
public float z;
}
enum Direction
{
West,
North,
East,
South
}
struct Path
{
public float distance;
public Direction dir;
}
class Program {
static void Main(string[] args)
{
//通过三个float类型的变量来表示一个敌人的坐标
//float enemy1X = 34;
//float enemy1Y = 1;
//float enemy1Z = 34;
//float enemy2X = 34;
//float enemy2Y = 1;
//float enemy2Z = 34;
//当使用结构体声明变量的时候,相当于使用结构体中所有的变量去声明
//Position enemy1Position;
//enemy1Position.x = 34;//可以通过.加上属性名来访问结构体中指定的变量
////使用结构体让程序变得更清晰
//Position enemy2Position;
Path path1;
path1.dir = Direction.East;
path1.distance = 1000;
}
}
}
五、传递参数及参数修饰符
1. 按值传递参数
C#方法中的参数默认是按照值传递
2. ref 修饰符
ref 修饰符 用于将 数值类型参数 进行引用传递
namespace _036_ref 修饰符 {
class Program {
static void Func(ref int a,ref int b)
{
int temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
int a = 10;
int b = 20;
Func(ref a, ref b);
Console.WriteLine(a.ToString()); //20
Console.WriteLine(b.ToString()); //10
}
}
}
namespace _036_ref 修饰符 {
class Program {
static void Func(ref string a,ref string b)
{
string temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
string a = "hello";
string b = "nihao";
Func(ref a,ref b);
Console.WriteLine(a.ToString()); //nihao
Console.WriteLine(b.ToString()); //hello
}
}
}
ref引用局部变量
需要C#7
int[] a = {
1, 2, 3 };
ref int b = ref a[1];
Console.WriteLine(a[1]);
b = 5;
Console.WriteLine(a[1]);
//输出
2
5
ref 引用返回值
需要C#7
static string a = "abc";
static ref string Method()
{
return ref a;
}
static void Main(string[] args)
{
ref string c = ref Method();
Console.WriteLine(a);
c = "hhh";
Console.WriteLine(a);
}
//输出
abc
hhh
3. out 修饰符
out 修饰符是传出参数,用于将方法内的数值用参数的形式传出,此外,带 out 修饰的参数,在方法结束前必须对它进行赋值。
namespace _036_out 修饰符 {
class Program {
static void Func(string a,out string b,out int c)
{
b = a;
c = 1;
}
static void Main(string[] args)
{
string a = "hello";
string b = "nihao";
//如果不想要传出参数,那么就用下划线 _ 代替
Func(a,out b,out _);
Console.WriteLine(a.ToString()); //hello
Console.WriteLine(b.ToString()); //hello
}
}
}
如果不想要其他的out参数,那么在调用方法的时候 用下划线 _ 代替,这叫做丢弃变量
//声明
static void Func(string a,out string b,out int c)
//调用
Func(a,out b,out _);
4. params 修饰符
params 修饰的参数必须是一维数组,这个参数必须是最后一个参数
namespace _036_params 修饰符 {
class Program {
static void Func(string a,params int[] c)
{
int sum = 0;
foreach(var i in c)
{
sum += i;
}
Console.WriteLine(sum.ToString());
}
static void Main(string[] args)
{
Func("",1,2,3); //6
}
}
}
5. 可选参数
可选参数就是给方法中 的形参添加一个默认值
void Func(string a = "fast",int[] c)
6. 命名参数
命名参数就是不管函数声明中参数的顺序,在调用过程中指定给哪个形参赋值。
此外命名参数还可以和值传递的混合使用,但是命名参数必须放在末尾。
还有可选参数和命名参数可以混合使用。
namespace _036_命名参数 {
class Program {
static void Func(int a,int b)
{
Console.WriteLine(a);
Console.WriteLine(b);
}
static void Main(string[] args)
{
int c = 1;
int d = 2;
Func(b:d, a:c);
}
}
}
7.隐式类型变量var
var a = "abc";
//等同于
string a = "abc";
//没有任何区别
六、类型默认值
所有类型的实例都有默认值。
char类型默认值 是 '\0'
bool类型默认值 是 false
所有数字类型默认值 是 0
所有引用类型默认值 是 null
static int a;
static bool b;
static char c;
static string d;
static void Main(string[] args)
{
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
}
//输出
0
False
七、null 运算符 ?
C#提供了两个null处理运算符: null合并运算符 和 null条件运算符。
1. null 合并运算符
null合并运算符写作 ?? 。意思是 “如果操作数不是null,则结果是操作数,否则结果是一个默认的值”。
namespace _036_显示转换和隐式转换 {
class Program {
static void Main(string[] args)
{
string ss = null;
//ss = "ts";
string res = ss ?? "nothing";
Console.WriteLine(res); //nothing
}
}
}
2. null条件运算符
null条件运算符写作 ?. 意思是如果左值为null,则为null,否则为该值内的成员。
例如 :
namespace _036_显示转换和隐式转换 {
class Program {
static void Main(string[] args)
{
string ss = null;
//ss = "NIHAO"; //输出nihao
ss = ss?.ToLower();
Console.WriteLine(ss); //输出空行
}
}
}
注意: null 两种运算符的混合使用如下
StringBuilder? sb = null;
string a = sb?.ToString() ?? "sb is null";
Console.WriteLine(a);
//输出
sb is null
八、语句特性
1. 带模式的 switch 语句(C#7)
object可以是任何类型的变量
static void TellMeTheType(object x)
{
switch (x)
{
//这里的 i 称作模式变量
case int i:
Console.WriteLine("It's an int");
Console.WriteLine($" {i} square is {i*i}");
break;
case double i:
Console.WriteLine("It's an double");
Console.WriteLine($" {i} square is {i * i}");
break;
case string i:
Console.WriteLine("It's an string");
Console.WriteLine("string is " + i);
break;
default:
break;
}
}
static void Main(string[] args)
{
TellMeTheType(12);
TellMeTheType("hello");
TellMeTheType(12.5);
}
//It's an int
//12 square is 144
//It's an string
//string is hello
//It's an double
//12.5 square is 156.25
2. switch 语句 case使用条件 when
类似if判断
switch(x)
{
case float f when f>100:
case double d when d>100:
case decimal m when m>100:
Console.WriteLine("We can refer to x here but not f or d or m");
break;
case null:
Console.WriteLine("Nothing here");
break;
}
3. 跳转语句
C#中的跳转语句有 break , continue,goto,return和throw
(1) goto语句使用
int myInteger = 5;
goto mylabel;//goto语句用来控制程序跳转到某个标签的位置
myInteger++;
mylabel:Console.WriteLine(myInteger);
Console.ReadKey();
如果在try语句里面执行goto,那么在goto之前会执行finally块内语句。
goto语句无法从finally块中跳到块外,除非用throw
(2) break 语句
退出当前最近一层的 for 循环
(3)continue 语句
跳过当前最近一层的 for 循环
(4) throw 语句
抛出异常
4. using 语句
这里的 using 语句和using指令用于命名空间不一样,这里的using语句主要作用是关闭一个持续流,例如自动关闭一个打开的文件,主要利用的是 调用 Dispose方法
{
//这样写,可以省略 a.close()方法
using var a = File.Open(@"D:\\a.txt", FileMode.Open);
}
//等同于
{
var a = File.Open(@"D:\\a.txt", FileMode.Open);
try
{
Console.ReadLine();
}
finally
{
//释放资源
a.Dispose();
}
}