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#多了几个变量,那么依旧将变量分为几个大类,

  1. 整数型:sbyte、byte、short、ushort、int、uint、long、ulong 和 char
  2. 浮点型:double、long
  3. 十进制类型:decimal
  4. 布尔类型:boolean
  5. 空字符串:string
  6. 空类型:可为空值的数据类型
    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# 中的两种表达式:

  1. lvalue:lvalue 表达式可以出现在赋值语句的左边或右边。
  2. rvalue:rvalue 表达式可以出现在赋值语句的右边,不能出现在赋值语句的左边。
     变量是 lvalue 的,所以可以出现在赋值语句的左边。数值是 rvalue 的,因此不能被赋值,不能出现在赋值语句的左边。下面是一个有效的语句:
    int g = 20;
    下面是一个无效的语句,会产生编译时错误:
    10 = 20;
    LV还是RV应该没必要特意去记,掌握初始化的规则就行。

2.4 C# 变量作用域

  1. 局部变量:在方法、循环、条件语句等代码块内声明的变量是局部变量,它们只在声明它们的代码块中可见。
void MyMethod()
{
    int localVar = 10; // 局部变量
    // ...
}
// localVar 在这里不可见
  1. 块级作用域
    在 C# 7及更高版本中,引入了块级作用域,即使用大括号 {} 创建的任何块都可以定义变量的作用域。
{
    int blockVar = 20; // 块级作用域
    // ...
}
// blockVar 在这里不可见
  1. 方法参数作用域
    方法的参数也有其自己的作用域,它们在整个方法中都是可见的。
void MyMethod(int parameter)
{
    // parameter 在整个方法中可见
    // ...
}
  1. 全局变量
    在类的成员级别定义的变量是成员变量,它们在整个类中可见,如果在命名空间级别定义,那么它们在整个命名空间中可见。
class MyClass
{
    int memberVar = 30; // 成员变量,在整个类中可见
}
  1. 静态变量作用域
    静态变量是在类级别上声明的,但它们的作用域也受限于其定义的类。
class MyClass
{
    static int staticVar = 40; // 静态变量,在整个类中可见
}
  1. 循环变量作用域
    在 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覆盖,不过输出结果来看并不是,也是吃了没基础的亏,底层数据结构的原理根本不清楚。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐