C#数据类型、变量和常量

应用程序中,对于数据的处理是最常见、也是最基本的功能;本文会介绍C#与.NET Framework中支持的基本数据类型、C#变量和常量的定义,以及引用类型和值类型的区别。

C#与.NET Framework数据类型

C#中有很丰富的数据类型,与.NET Framework数据类型对应关系如下表所示。

C#类型.NET Frameowrk类型C#字面量类型字符取值范围
sbyteSByte结构-128到+127的整数(1字节)
byteByte结构0和255的无符号整数(1字节)
shortInt16结构-32,768到+32,767 的整数(2字节)
ushortUInt16结构0到65535 的无符号整数(2字节)
intInt32结构-2,147,483,648到+2,147,483,647 的整数(4字节)
uintUInt32结构0到4,294,967,295 的无符号整数(4字节)
longInt64结构L,l-9,223,372,036,854,775,808到+9,223,372,036,854,775,807 的整数(8字节)
ulongUInt64结构UL,ul0到18,446,744,073,709,551,615的无符号整数(8字节)
floatSingle结构F,f-3.402823e38到+3.402823e38的单精度数字(占用4字节)
doubleDouble结构D,d-1.79769313486232e308到+1.79769313486232e308的双精度数位(占用8字节)
decimalDecimal结构M,m-79,228,162,514,264,337,593,543,950,335到+79,228,162,514,264,337,593,543,950,335的十进制数(16字节)
boolBoolean结构true或false值,在.NET Framework中定义为True和False值。
charChar结构Unicode字符(2字节)
stringString类Unicode字符序列,0到231个Unicode字符。定义为不可变字符串。
objectObject类任何类型,是.NET Framework所有类型的终极基类。
DateTime结构公元0001年1月1日00:00:00到9999年12月31日23:59:59(8字节)

下面先来了解数值类型,后续还会有各种数据类型的详细讨论。

数值类型

C#中的数值包括整数类型、浮点数类型和decimal类型。

整数类型包括sbyte、byte、short、ushort、int、uint、long、ulong,用于处理不包含小数部分的数据;其中,byte、ushort、uint和ulong类型为无符号整数类型,只能处理大于等于0的整数。C#中,十进制整数字面量直接使用0到9的数字和正负号书写。此外,还可以使用0b前缀定义二进制数值,如0b1011表示十进制的11;使用0x前缀十六进制数值,如0x0B同样表示十进制的11。

整数字面量的默认类型为int,如果需要指定字面量为其它类型,可以使用字面量类型字符,如123F和123f为单精度浮点数(float)、123D和123d是双精度浮点数(double)。

C#中的浮点数据类型包括float和double,可以处理包含小数部分的数据。浮点数字面量的默认类型为double,单精度数值应使用F或f类型字符,如1.23F、1.23f。

decimal是C#原生数值类型中处理数据范围最大的,可用于科学计算等场景。

变量

变量是代码中处理数据的标识符,包括变量名、数据类型和数据;而且,变量的数据在代码运行过程中是可以根据需要改变的。C#中定义变量的格式为“<数据类型> <变量名>=<数据>”。下面的代码定义了int类型的变量,并显示其值。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            int x=10, y = 99;
            Console.WriteLine(x);  // 10
            Console.WriteLine(y);  // 99
            x = 98;
            Console.WriteLine(x);  // 98
        }
    }
}

代码中,变量名可以使用字母开始,并使用字母、数字和下画线组成,但不应使用关键字和保留字命名。

常量

常量应在定义时指定数据,并且在代码执行过程中不能修改其数据,C#中定义常量需要使用const关键字,格式为“const <数据类型> <常量名>=<数据>”,下面的代码演示了常量的基本应用。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            const int MAX_SIZE = 255;
            Console.WriteLine(MAX_SIZE);  // 255
        }
    }
}

习惯上,常量名使用大写字母、下画线和数字组成;实际工作中可以根据项目开发约定使用统一的命名规则。

引用类型和值类型

在本文开始的C#和.NET Framework数据类型对应表中,.NET Framework类型中包含类(class)和结构(struct)两种,其中,类是引用类型,结构是值类型,对应的C#类型也是这样。

引用类型和值类型在内存的管理方式上有所不同,一般来讲,引用类型,如某个类类型的对象,会指向类的实例;将对象赋值给另外一个对象时,并不会复制实例,两个对象都会指向同一实例,修改一个对象的数据时也会反映到另一个对象。下面的代码,会在C1类中添加Name字段(/cfx/demo/C1.cs)。

C#
using System;

namespace cfx.demo
{
    public class C1
    {
        //
        public string Name = "";
        //
        public static void Hello()
        {
            Console.WriteLine("Hello");
        }
    }
}

下面的代码,在Program.cs文件进行测试。

C#
using System;
using cfx.demo;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            C1 obj1 = new C1();
            obj1.Name = "Tom";
            C1 obj2 = obj1;
            Console.WriteLine(obj1.Name);  // Tom
            Console.WriteLine(obj2.Name);  // Tom
            obj2.Name = "Jerry";
            Console.WriteLine(obj1.Name);  // Jerry
            Console.WriteLine(obj2.Name);  // Jerry
        }
    }
}

代码中,首先定义obj1对象,它指向C1类的一个实例(使用new关键字创建),并将Name字段设置为"Tom",然后,将obj1对象赋值给obj2对象,可以看到,两个对象的Name字段值都是"Tom"。接下来,通过obj2对象修改Name字段的数据为"Jerry",最后,显示两个对象的Name字段值,结果都是Jerry。也就是说,obj1和obj2两个对象指向的是同一个C1类的实例。

值类型,如数值变量直接指向数据所在内存区域,新的变量会重新分配内存区域,修改一个变量的数据不会影响另一个变量。下面的代码演示了值类型的使用。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 10;
            int y = x;
            Console.WriteLine(x);  // 10
            Console.WriteLine(y);  // 10
            y = 99;
            Console.WriteLine(x);  // 10
            Console.WriteLine(y);  // 99
        }
    }
}

代码中,首先定义了int类型的变量x,并赋值为10;然后定义了int类型的变量y,并将x的数据赋值到y中,显示两个变量的值都是10;接下来修改y的值为99,显示两个变量的数据分别是10和99,即修改y的值并不影响x。