Unity C# 爆破计划(二):变量与数据

本文介绍了C#中的变量、数据类型及其策略,包括变量与常量、简单类型如整型、浮点型、布尔型,以及可空类型和引用类型。还讲解了类型转换的方法,如强制类型转换、ToType方法和Parse方法,并讨论了C#的运算符,包括算术、关系、逻辑和位运算符。此外,还提到了运算符优先级和隐式类型var的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


二、变量与数据

Covers:变量与常量、类型与运算符

变量与常量

懒得废话:

  • C# 对声明和定义不作区分(在 C++ 中定义指发生了内存分配),声明时就发生了定义;
  • 允许变量先定义后初始化,TYPE VARNAME; 定义变量 VARNAME 但不初始化;
  • 等号 = 是 C# 的赋值运算符;
  • 常量修饰符为 const

类型策略

C# 是强类型语言,因此数据必须有明确的静态类型;完全面向对象意味着一切都是对象,派生自 System.Object 类,包括其内置类型也是如此。

C# 中类型只有两种:引用(实际上还有指针类型,但它仅在不安全模式下可用,我们不管它):

  • 值类型的对象存放在栈上;
  • 引用类型的对象在栈上存放一个“指针”(并非 C/C++ 中的指针,它自动解引用,行为上与 C++ 中的引用类似),所指向的值(或引用)对象则存放在“托管堆”中,由 CLR 自动管理;
  • 所有值类型的对象都具有 .ToString() 方法,可以转换为字符串;用于打印时,也可使用标准格式字符串(见后文)。

简单类型

C++ 中用于存放常规数据的内置类型,在 C# 中称为“简单类型”,是 System 命名空间下提供的若干类,它们都是值类型;所有简单类型都有一个别名,如 intchar 等,以保持 C++ 风格的变量声明语法。

下文将一口气介绍多数常用的简单类型。

整型

整型就是整数,C# 中默认整型数据为 int 类;System 命名空间提供的所有整型类包括:

语法(别名)占用空间取值范围
int4 B = 32 bit − 2 31 ~ 2 31 − 1 -2^{31} ~ 2^{31}-1 2312311
uint4 B = 32 bit 0 ~ 2 32 − 1 0 ~ 2^{32}-1 02321
sbyte1 B = 8 bit − 2 7 ~ 2 7 − 1 -2^{7} ~ 2^{7}-1 27271
byte1 B = 8 bit 0 ~ 2 8 − 1 0 ~ 2^{8}-1 0281
short2 B = 16 bit − 2 15 ~ 2 15 − 1 -2^{15} ~ 2^{15}-1 2152151
ushort2 B = 16 bit 0 ~ 2 16 − 1 0 ~ 2^{16}-1 02161
long8 B = 64 bit − 2 63 ~ 2 63 − 1 -2^{63} ~ 2^{63}-1 2632631
ulong8 B = 64 bit 0 ~ 2 64 − 1 0 ~ 2^{64}-1 02641
char2 B = 16 bit(Unicode)

C# 中,不能将整型隐式转换到 char(单字符)型,char 专用于存储一个字符数据。

浮点型

浮点型就是实数,C# 中默认浮点型数据为 double 类;System 命名空间提供的所有浮点型类包括:

语法(别名)占用空间小数精度
double、后缀 d8 B = 64 bit15~16 位
float、后缀 f4 B = 32 bit7 位
decimal、后缀 m16 B = 128 bit28~29 位

**注意:**C# 中,十进制实型 decimal 与两种浮点型之间没有隐式和强制类型转换,不可同时使用在一个表达式中。

布尔型

布尔型就是逻辑量,别名为 bool,取值只能是 truefalse 之一,可以直接向控制台打印。

可空类型

C# 提供了一种特殊的值类型,即 可空类型(nullable type),它依附于一个主类型而存在,允许该类型的取值为 null(表示“空、未赋值、无效”)。

在任何值类型右侧加一个问号 ? 作为其类型修饰,则表示基于该类型的可空类型,如 int? 表示“可空的 32 位整型”,其取值除 int 型的常规取值范围外,还可以取 null:

int? num = 65536;
Console.WriteLine(num);
num = null;
Console.WriteLine(num);

上面的代码输出一行“65536”和一个空行。

引用类型

C# 内置的引用类型包括对象类、动态类和字符串类。

对象类

System.Object 类是 C# 的创世类,它还有个别名叫 object。对象类的对象(简称对象对象,听起来好奇怪)可以赋以任何其他类型的值。

给对象对象赋以其他类型的值,称为 装箱(boxing,没错你也可以翻译成拳击),在这个过程中发生了从等号右侧类型到对象类的隐式转换:

// Boxing example 1 (int converted to object):
object age = 19;

// Boxing example 2 (char converted to object):
char character = 'z';
object boxed = character;

从已装箱的对象对象中取回原来的值,称为 拆箱(unboxing),在这个过程中发生了逆向的显式转换,需要使用显式转换(见后文)来完成:

// Unboxing:
char another = (char) boxed;

对象类能够赋以任何类型的值,这并没有破坏 C# 的强类型性,因为它是一种引用类型,本质上只是一枚指针,对对象对象的类型检查发生在编译时。

动态类

.NET 4.0 引入的动态类 dynamic 是对对象类的一种特殊处理,它在编译后就是 System.Object 类的对象,但在编译期间不进行类型检查:

// Dynamic object:
dynamic name = Console.ReadLine();

// This is Ok:
name = 1.414;

在非必要时不要使用这种类型的引用。

字符串类

字符串类也是一种引用类型,可以赋值为任意长度的字符(char)的序列,为字符串对象赋值有两种方式:

// Assign to a string, method 1:
string name = "Karl Marx"

// Assign to a string, method 2:
string directory = @"C:\Dev\Program";

@ 引导字符串时,将忽略其中的 转义字符

类型转换

C# 的隐式类型转换 没有 C++ 那么复杂,它 只发生在安全(不发生窄化)的情况下,例如从 short 转化为 int;其他情况下需要进行显式转换。

强制类型转换

使用 类型转换运算符 (TYPE) 进行强制类型转换:

int num = 131072;
short narrow = (short) num;
Console.WriteLine("num = " + num);
Console.WriteLine("narrow = " + narrow);

上面的代码产生的输出:

num = 131072
narrow = 0

能够通过编译,但 narrow 中的数据是无效的。

ToType 方法

使用 C# 内置 System.Convert 类的“ToType”方法(Type 可以是各种内置类型,如 Double、Int64 等)来完成类型转换:

int number = Convert.ToInt32(2.71828);

上面的 ToInt32 转换是 四舍五入 的。

Console.WriteLine(Convert.ToDateTime("2021年4月14日 下午2:15"));

输出“2020/4/14 14:15:00”。

Parse 方法

内置类型的 Parse 方法可以从字符串解析出其他类型的数据,如:

bool flag = bool.Parse("true");
int number = int.Parse("233");
double pi = double.Parse("3.1416");
var time = DateTime.Parse("2021-4-14 PM 2:15");

自动类型推导

从 .NET 3.0(我们现在用的是 5.0)开始,可以使用隐式类型 var,该类型并非弱类型,而是根据变量的初始化值,在编译时自动判断类型;使用隐式类型声明变量但不初始化,或初始化后又赋值为其他数据类型,都会导致编译错误:

var name = "Bug";   // Ok, "name" is inferred to be string
var gender;         // Bad
name = 1.23;        // Bad, "name" is already defined as string

实际编程中要不要使用隐式类型,取决于个人习惯或公司的代码风格规范。

运算符

C# 运算符分为 6 类:

  1. 算术运算符
  2. 关系运算符
  3. 布尔运算符
  4. 位运算符
  5. 赋值运算符
  6. 其他
算术运算符
  • 四则运算:+-*/,除法的结果符合 C/C++ 的习惯:“3 / 2 返回 1,3.0 / 2 返回 1.5”
  • 模除:%,也就是取余
  • 自增自减:++--,前后置的结果符合 C/C++ 的习惯:“a++ 返回 a 原值,++a 返回 a 新值”
关系运算符
  • 检等运算:相等 ==,不等 !=
  • 不等运算:大于 >,小于 <,不小于 >=,不大于 <=
逻辑运算符
  • 与:&&
  • 或:||
  • 非:!
位运算符
  • 位与:&
  • 位或:|
  • 按位异或:^
  • 按位取非:~
  • 移位:<<>>,空位补零
赋值运算符
  • 简单赋值:=
  • 运算兼赋值:+=-=*=/=%=&=|=^=<<=>>=
其他
  • 括号:(EXPR),将 EXPR 的运算优先级提高

  • 三目运算:BOOL_STATE ? IF_TRUE : IF_FALSE

  • 取数据量:sizeof(EXPR),返回字节数

  • 强制类型转换:(TYPE) EXPR

  • 鉴型运算符:EXPR is TYPE,返回布尔值,反映表达式 EXPR 是否兼容于 TYPE(是否为 TYPE,或父类型是 TYPE),永不抛出异常

  • 拆箱运算符:EXPR as TYPE,等价于 EXPR is TYPE ? (TYPE) EXPR : (TYPE) null,如果 EXPR 不兼容于 TYPE(类型不兼容或空引用),则返回 null,否则返回将 EXPR 强制转换为 TYPE 后的结果,其实就是我们前面讲过的拆箱。这里要注意 TYPE 必须为可空类型,因为 as 本身就暗示了表达式可能返回 null:

    int? num = 65536;
    object obj = num;
    Console.WriteLine(obj as int?);
    
  • 空值合并运算:EXPR ?? DEFAULT,等价于 EXPR == null ? DEFAULT : EXPR,如果 EXPR 不为 null,则返回 EXPR,否则返回 DEFAULT

运算符优先级

C# 的运算符优先级与 C++ 基本一致,可参考 该页面


T.B.C.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值