跟随菜鸟学习C#-day2
1.类型转换
顾名思义,将一个数据类型转换为另一个数据类型的过程
类型转换分为两种:隐式类型转换与显式类型转换(也叫强制类型转换)
1-1.隐式类型转换
隐式类型转换是较小范围的数据类型转换为较大范围的数据类型时,编译器会自动完成类型转换,这些转换是C#默认以安全方式进行转换,不会导致丢失数据.
例如,从 int 到 long,从 float 到 double 等。
byte b = 10;
int i = b; // 隐式转换,不需要显式转换
int intValue = 42;
long longValue = intValue; // 隐式转换,从 int 到 long
1-2.显式类型转换
显式类型转换即强制类型转换,需要程序员在代码中明确指定。与隐式类型转换相反,显式类型转换是较大数据范围转换为较小数据范围,而且强制转换会造成数据丢失,例如将int转换为byte
int i = 10;
byte b = (byte)i; // 显式转换,需要使用强制类型转换符号
强制转换为整数类型:
double doubleValue = 3.14;
int intValue = (int)doubleValue; // 强制从 double 到 int,数据可能损失小数部分
强制转换为浮点数类型:
int intValue = 42;
float floatValue = (float)intValue; // 强制从 int 到 float,数据可能损失精度
强制转换为字符串类型:
int intValue = 123;
string stringValue = intValue.ToString(); // 将 int 转换为字符串
现在的疑惑是如果忘记数据范围的大小,在编译时,显式数据转换错误是否会直接显示编译错误?如果编译不显示错误,除非数据出现问题,否则那这类转换问题还不是特别容易查找,是一个隐患。
1-3.内置类型转换方法
整体看下来写法为To+类型名称(首字母大写,如ToBoolean(如果可能的话,把类型转换为布尔型。))
这些方法都定义在 System.Convert 类中,使用时需要包含 System 命名空间。它们提供了一种安全的方式来执行类型转换,因为它们可以处理 null值,并且会抛出异常,如果转换不可能进行。
例如,使用 Convert.ToInt32 方法将字符串转换为整数:
string str = "123";
int number = Convert.ToInt32(str); // 转换成功,number为123
除此之外,还有使用 Parse 方法转换
Parse 方法用于将字符串转换为对应的数值类型,如果转换失败会抛出异常。
string str = "123.45";
double d = double.Parse(str);
使用 TryParse 方法
TryParse 方法类似于 Parse,但它不会抛出异常,而是返回一个布尔值指示转换是否成功。
string str = "123.45";
double d;
bool success = double.TryParse(str, out d);
if (success) {
Console.WriteLine("转换成功: " + d);
} else {
Console.WriteLine("转换失败");
}
至于自定义转换,等后面需要的时候再看吧
1-4.总结
范围大的数据转为范围小的数据需要程序员转换,这个过程称作显式数据转换,过程中可能丢失数据(包括精度,数字等),而隐式数据转换则不会丢失数据且自动转换。转换方法有内置方法、Convert、Parse、TryParse以及自定义转换等。不过结合前面学的装箱拆箱,它们是否也算是另一种方式的数据转换?(后续AI解释装箱拆箱 - 不改变数据本身,只改变存储方式)
2.变量
2.1变量类型
在day1的时候初步了解,当时觉得和Java变量差不多,不过C#多了几个变量,那么依旧将变量分为几个大类,
- 整数型:sbyte、byte、short、ushort、int、uint、long、ulong 和 char
- 浮点型:double、long
- 十进制类型:decimal
- 布尔类型:boolean
- 空字符串:string
- 空类型:可为空值的数据类型
C#变量对比Java多了标红的变量,需要注意的是decimal是在C#4.0版本加入的,菜鸟原话为"它允许在运行时推断变量的类型。这在一些特殊情况下很有用,但通常最好使用静态类型以获得更好的性能和编译时类型检查。"
dynamic dynamicVariable = "This can be any type";
2.2变量定义
<data_type> <variable_list>;
int i, j, k;
char c, ch;
float f, salary;
double d;
您可以在变量定义时进行初始化:
int i = 100;
变量的命名规则与Java大同小异,甚至可以说一样,也遵守驼峰命名规则。
2.3变量初始化
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:variable_name = value; 变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成,如下所示:
<data_type> <variable_name> = value;
一些实例
int d = 3, f = 5; /* 初始化 d 和 f. */
byte z = 22; /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x'; /* 变量 x 的值为 'x' */
接受来自用户的值
System 命名空间中的 Console 类提供了一个函数ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中。
int num;
num = Convert.ToInt32(Console.ReadLine());
函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。
2.3.1 C# 中的 Lvalues 和 Rvalues
C# 中的两种表达式:
- lvalue:lvalue 表达式可以出现在赋值语句的左边或右边。
- rvalue:rvalue 表达式可以出现在赋值语句的右边,不能出现在赋值语句的左边。
变量是 lvalue 的,所以可以出现在赋值语句的左边。数值是 rvalue 的,因此不能被赋值,不能出现在赋值语句的左边。下面是一个有效的语句:int g = 20;
下面是一个无效的语句,会产生编译时错误:10 = 20;
LV还是RV应该没必要特意去记,掌握初始化的规则就行。
2.4 C# 变量作用域
- 局部变量:在方法、循环、条件语句等代码块内声明的变量是局部变量,它们只在声明它们的代码块中可见。
void MyMethod()
{
int localVar = 10; // 局部变量
// ...
}
// localVar 在这里不可见
- 块级作用域
在 C# 7及更高版本中,引入了块级作用域,即使用大括号 {} 创建的任何块都可以定义变量的作用域。
{
int blockVar = 20; // 块级作用域
// ...
}
// blockVar 在这里不可见
- 方法参数作用域
方法的参数也有其自己的作用域,它们在整个方法中都是可见的。
void MyMethod(int parameter)
{
// parameter 在整个方法中可见
// ...
}
- 全局变量
在类的成员级别定义的变量是成员变量,它们在整个类中可见,如果在命名空间级别定义,那么它们在整个命名空间中可见。
class MyClass
{
int memberVar = 30; // 成员变量,在整个类中可见
}
- 静态变量作用域
静态变量是在类级别上声明的,但它们的作用域也受限于其定义的类。
class MyClass
{
static int staticVar = 40; // 静态变量,在整个类中可见
}
- 循环变量作用域
在 for 循环中声明的循环变量在循环体内可见
for (int i = 0; i < 5; i++)
{
// i 在循环体内可见
}
// i 在这里不可见
对某些变量作用范围还是有点模糊,只能在后面的应用中熟悉了,目前只是知道变量大概在代码块中可以使用。
3.常量
既然都有变量了,那肯定也得有常量,顾名思义,就是保持值不变,不能被修改。
3.1 整数常量
整数常量对我来说这是全新概念,我也不太清楚整数常量在实际应用中算不算重要,先前学习Java貌似从来没接触过整数常量,也可能接触了,但没有专门的术语,只是初步了解了常量概念。而菜鸟对整数常量的原文是整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。至于菜鸟上的整数常量实例我就不照搬过来了,各类八进制和十进制还有十六进制看着头大。
3.2 浮点常量
菜鸟原文:一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。使用浮点形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。
3.3 字符常量
菜鸟原文:字符常量是括在单引号里,例如,'x',且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 'x')、一个转义序列(例如 '\t')或者一个通用字符(例如 '\u02C0')。 在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符 tab(\t)。字符常量使用过的,最经典的有\n、\等。
3.4 字符串常量
菜鸟原文:字符串常量是括在双引号 "" 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符。使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。
3.5 定义常量
常量是使用 const 关键字来定义的 。定义一个常量的语法如下:
const <data_type> <constant_name> = value;
菜鸟最后给了一段实例,一开始没看懂,所以还是有思考的价值的。
using System;
public class ConstTest
{
class SampleClass
{
public int x;
public int y;
public const int c1 = 5;
public const int c2 = c1 + 5;
public SampleClass(int p1, int p2)
{
x = p1;
y = p2;
}
}
static void Main()
{
SampleClass mC = new SampleClass(11, 22);
Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y);
Console.WriteLine("c1 = {0}, c2 = {1}",
SampleClass.c1, SampleClass.c2);
}
}
看不懂的地方是最后两行控制台输出的地方,按理来说mC会把上面创建的c1与c2覆盖,不过输出结果来看并不是,也是吃了没基础的亏,底层数据结构的原理根本不清楚。
更多推荐



所有评论(0)