类型 | 描述 | 范围 | 例子 |
sbyte | 8-bit 有符号整数类型 | –128...127 | sbyte val = 12; |
short | 16-bit有符号整数类型 | –32,768...32,767 | short val = 12; |
int | 32-bit有符号整数类型 | –2,147,483,648...2,147,483,647 | int val = 12; |
long | 64-bit有符号整数类型 | –9,223,372,036,854,775,808 ...9,223,372,036,854,775,807 |
long val1 = 12; long val2 = 34L; |
byte | 8-bit无符号整数类型 | 0...255 | byte val1 = 12; byte val2 = 34U; |
ushort | 16-bit无符号整数类型 | 0...65,535 | ushort val1 = 12; ushort val2 = 34U; |
uint | 32-bit无符号整数类型 | 0...4,294,967,295 | uint val1 = 12; uint val2 = 34U; |
ulong | 64-bit无符号整数类型 | 0...18,446,744,073,709,551,615 | ulong val1 = 12; ulong val2 = 34U; ulong val3 = 56L; ulong val4 = 78UL; |
float | 单精度浮点数类型 | 1.5 × 10−45 至 3.4 × 1038,7位精度 | float val = 1.23F; |
double | 双精度浮点数类型 | 5.0 × 10−324 至1.7 × 10308,15 位精度 | double val1 = 1.23; double val2 = 4.56D; |
bool | 布尔类型类型; 一个布尔类型数据不是真就是假 | true,false | bool val1 = true; bool val2 = false; |
char | 字符类型; 一个字符数据是一个Unicode字符 | char val = 'h'; | |
decimal | 精确十进制类型,有28个有效位 | 1.0 × 10−28 至 7.9 × 1028,28位精度 | decimal val = 1.23M; |
object | 所有其它类型的最根本的基础类型 | object o = null; | |
string | 字符串类型,一个字符串是一个Unicode字符序列 | string s= "Hello"; |
sbyte
可使用下述方法声明并初始化 sbyte 类型的变量:
sbyte sByte1 = 127;
在以上声明中,整数 127 从 int 隐式转换为 sbyte。 如果整数超出了 sbyte 的范围,将产生编译错误。
调用重载方法时必须使用强制转换。 以下面使用 sbyte 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {}
public static void SampleMethod(sbyte b) {}
使用 sbyte 强制转换可保证调用正确的类型,例如:
// 用int参数调用方法:
SampleMethod(5);
// 用sbyte参数调用方法:
SampleMethod((sbyte)5);
存在从 sbyte 到 short、int、long、float、double 或 decimal 的预定义隐式转换。
不能将存储大小更大的非文本数值类型隐式转换为 sbyte 类型。 例如,请看以下两个 sbyte 变量 x 和 y:
sbyte x = 10, y = 20;
以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int。
sbyte z = x + y; // 错误
若要更正此问题,请对该表达式执行强制转换,如下例所示:
sbyte z = (sbyte)(x + y); // 正确
但是,在目标变量具有相同或更大的存储大小时,使用下列语句是可能的:
sbyte x = 10, y = 20;
int m = x + y;
long n = x + y;
还请注意,不存在从浮点型到 sbyte 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
sbyte x = 3.0; // 错误
sbyte y = (sbyte)3.0; // 正确
short
可如下例所示声明并初始化 short 类型的变量:
short x = 32767;
在以上声明中,整数 32767 从 int 隐式转换为 short。 如果整数的长度超过了 short 存储位置的大小,则将产生编译错误。
调用重载方法时必须使用强制转换。 以下面使用 short 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {}
public static void SampleMethod(short s) {}
使用 short 强制转换可保证调用正确的类型,例如:
SampleMethod(5); // 用int参数调用方法
SampleMethod((short)5); // 用short参数调用方法
存在从 short 到 int、long、float、double 或 decimal 的预定义隐式转换。
不能将存储大小更大的非文本数值类型隐式转换为 short 类型。 例如,请看以下两个 short 变量 x 和 y:
short x = 5, y = 12;
以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int 类型。
short z = x + y; // 错误
若要解决此问题,请使用强制转换:
short z = ( short )(x + y); // 正确
但是,在目标变量具有相同或更大的存储大小时,使用下列语句是可能的:
int m = x + y;
long n = x + y;
不存在从浮点型到 short 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
short x = 3.0; // Error: 错误
short y = (short)3.0; // OK: 正确
int
可以声明并初始化 int 类型的变量,例如:
int i = 123;
如果整数没有后缀,则其类型为以下类型中可表示其值的第一个类型:int、uint、long、ulong。 在此例中为 int 类型。
存在从 int 到 long、float、double 或 decimal 的预定义隐式转换。 例如:
// 123是一个int,因此这里发生了一个隐式转换:
float f = 123;
存在从 sbyte、byte、short、ushort 或 char 到 int 的预定义隐式转换。 例如,如果不进行强制转换,下面的赋值语句将产生编译错误:
long aLong = 22;
int i1 = aLong; // 错误
int i2 = (int)aLong; // 正确
还请注意,不存在从浮点型到 int 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
int x = 3.0; // 错误
int y = (int)3.0; // 正确
long
可如下例所示声明并初始化 long 类型的变量:
long long1 = 4294967296;
如果整数没有后缀,则其类型为以下类型中可表示其值的第一个类型:int、uint、long、ulong。 在上例中,它是 long 类型,因为它超出了 uint 的范围。
还可以像下面这样,在 long 类型中使用后缀 L:
long long2 = 4294967296L;
当使用后缀 L 时,将根据整数的大小确定它的类型为 long 还是 ulong。 在此例中,它是 long,因为它小于 ulong 的范围的下限。
此后缀常用于调用重载方法。 以下面使用 long 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {}
public static void SampleMethod(long l) {}
使用后缀 L 可保证调用正确的类型,例如:
SampleMethod(5); // 用int参数调用方法
SampleMethod(5L); // 用long参数调用方法
可在同一个表达式中同时使用 long 类型和其他数值整型,这时表达式的计算结果为 long(在关系表达式或布尔表达式中为 bool)类型。 例如,下列表达式计算为 long:
898L + 88
说明 |
---|
也可用小写字母“l”作后缀。 但是,因为字母“l”容易与数字“1”混淆,会生成编译器警告。为清楚起见,请使用“L”。 |
有关兼用浮点型和整型的算术表达式的信息,请参见 float 和 double。
存在从 long 到 float、double 或 decimal 的预定义隐式转换。 其他情况下必须使用显式转换。 例如,不使用显式类型转换时,下列语句将产生编译错误:
int x = 8L; // 错误
int x = (int)8L; // 正确
存在从 sbyte、byte、short、ushort、int、uint 或 char 到 long 的预定义隐式转换。
还请注意,不存在从浮点型到 long 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
long x = 3.0; // 错误
long y = (long)3.0; // 正确
byte
可如下例所示声明并初始化 byte 类型的变量:
byte myByte = 255;
在以上声明中,整数 255 从 int 隐式转换为 byte。 如果整数超出了 byte 的范围,将产生编译错误。
存在从 byte 到 short、ushort、int、uint、long、ulong、float、double 或 decimal 的预定义隐式转换。
不能将更大存储大小的非文本数值类型隐式转换为 byte。 例如,请看以下两个 byte 变量 x 和 y:
byte x = 10, y = 20;
以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int 类型。
byte z = x + y;// 错误
若要解决此问题,请使用强制转换:
byte z = (byte)(x + y);// 正确
但是,在目标变量具有相同或更大的存储大小时,使用下列语句是可能的:
int x = 10, y = 20;
int m = x + y;
long n = x + y;
同样,不存在从浮点型到 byte 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
byte x = 3.0; // 错误
byte y = (byte)3.0;// 正确
调用重载方法时,必须使用显式转换。 以下面使用 byte 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {}
public static void SampleMethod(byte b) {}
使用 byte 强制转换可保证调用正确的类型,例如:
// 调用int参数的方法:
SampleMethod(5);
// 用byte参数调用方法:
SampleMethod((byte)5);
ushort
可如下例所示声明并初始化 ushort 类型的变量:
ushort myShort = 65535;
在以上声明中,整数 65535 从 int 隐式转换为 ushort。 如果整数超出了 ushort 的范围,将产生编译错误。
调用重载方法时,必须使用强制转换。 以下面使用 ushort 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {} public static void SampleMethod(ushort s) {}
使用 ushort 强制转换可保证调用正确的类型,例如:
// 调用int参数的方法: SampleMethod(5); // 使用ushort参数调用该方法: SampleMethod((ushort)5);
存在从 ushort 到 int、uint、long、ulong、float、double 或 decimal 的预定义隐式转换。
存在从 byte 或 char 到 ushort 的预定义隐式转换。 其他情况下必须使用显式转换。 例如,请看以下两个 ushort 变量 x 和 y:
ushort x = 5, y = 12;
以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int。
ushort z = x + y; // 错误
若要解决此问题,请使用强制转换:
ushort z = (ushort)(x + y); // 正确
但是,在目标变量具有相同或更大的存储大小时,使用下列语句是可能的:
int m = x + y; long n = x + y;
还请注意,不存在从浮点型到 ushort 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
// 错误 ushort x = 3.0; // 正确 ushort y = (ushort)3.0;
uint
可如下例所示声明并初始化 uint 类型的变量:
uint myUint = 4294967290;
如果整数没有后缀,则其类型为以下类型中可表示其值的第一个类型:int、uint、long、ulong。 在此例中,它是 uint:
uint uInt1 = 123;
还可以像下面这样使用后缀 u 或 U:
uint uInt2 = 123U;
当使用后缀 U 或 u 时,将根据文本的数值来确定文本的类型是 uint 还是 ulong。 例如:
Console.WriteLine(44U.GetType()); Console.WriteLine(323442434344U.GetType());
此代码先后显示 System.UInt32 和 System.UInt64(它们分别是 uint 和 ulong 的基础类型),因为第二个文本太大,无法用 uint 类型来存储。
存在从 uint 到 long、ulong、float、double 或 decimal 的预定义隐式转换。 例如:
float myFloat = 4294967290; // 正确
存在从 byte、ushort 或 char 到 uint 的预定义隐式转换。 否则必须使用显式转换。 例如,如果不进行强制转换,下面的赋值语句将产生编译错误:
long aLong = 22; // 错误 uint uInt1 = aLong; // 正确 uint uInt2 = (uint)aLong;
还请注意,不存在从浮点型到 uint 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
// 错误 uint x = 3.0; // 正确 uint y = (uint)3.0;
ulong
可如下例所示声明并初始化 ulong 类型的变量:
ulong uLong = 9223372036854775808;
如果整数没有后缀,则其类型为以下类型中可表示其值的第一个类型:int、uint、long、ulong。 在上面的示例中,它是 ulong 类型。
还可根据以下规则使用后缀指定文字类型:
-
如果使用 L 或 l,那么根据整数的大小,可以判断出其类型为 long 还是 ulong。
说明 注意也可用小写字母“l”作后缀。 但是,因为字母“l”容易与数字“1”混淆,会生成编译器警告。为清楚起见,请使用“L”。
-
如果使用 U 或 u,那么根据整数的大小,可以判断出其类型为 uint 还是 ulong。
-
如果使用 UL、ul、Ul、uL、LU、lu、Lu 或 lU,则整数的类型为 ulong。
例如,以下三个语句的输出将为系统类型 UInt64,此类型对应于别名 ulong:
Console.WriteLine(9223372036854775808L.GetType()); Console.WriteLine(123UL.GetType()); Console.WriteLine((123UL + 456).GetType());
此后缀常用于调用重载方法。 以下面使用 ulong 和 int 参数的重载方法为例:
public static void SampleMethod(int i) {} public static void SampleMethod(ulong l) {}
在 ulong 参数后加上后缀可保证调用正确的类型,例如:
SampleMethod(5); // 用int参数调用方法 SampleMethod(5UL); // 用ulong参数调用该方法
存在从 ulong 到 float、double 或 decimal 的预定义隐式转换。
不存在从 ulong 到任何整型的隐式转换。 例如,不使用显式类型转换时,下列语句将产生编译错误:
long long1 = 8UL; // 错误
存在从 byte、ushort、uint 或 char 到 ulong 的预定义隐式转换。
同样,不存在从浮点型到 ulong 类型的隐式转换。 例如,除非使用显式强制转换,否则以下语句将生成一个编译器错误:
// 错误 ulong x = 3.0; // 正确 ulong y = (ulong)3.0;
float
默认情况下,赋值运算符右侧的实数被视为 double。 因此,应使用后缀 f 或 F 初始化浮点型变量,如以下示例中所示:
float x = 3.5F;
如果在以上声明中不使用后缀,则会因为您尝试将一个 double 值存储到 float 变量中而发生编译错误。
可在一个表达式中兼用数值整型和浮点型。 在此情况下,整型将转换为浮点型。 根据以下规则计算表达式:
浮点表达式可以包含下列值集:
-
正零和负零
-
正无穷和负无穷
-
非数字值 (NaN)
-
有限的非零值集
有关这些值的更多信息,请参见 IEEE 网站上的“IEEE Standard for Binary Floating-Point Arithmetic”(二进制浮点算法的 IEEE 标准)。
在下面的示例中,包含 int、short 和 float 类型的数学表达式得到一个 float 结果。 (请记住 float 是 System.Single 类型的别名。)请注意,表达式中没有 double。
class FloatTest { static void Main() { int x = 3; float y = 4.5f; short z = 5; var result = x * y / z; Console.WriteLine("The result is {0}", result); Type type = result.GetType(); Console.WriteLine("result is of type {0}", type.ToString()); } } /* 输出: The result is 2.7 result is of type System.Single。 // float'是'Single'的别名 */
double
默认情况下,赋值运算符右侧的实数被视为 double。 但是,如果希望整数被视为 double,请使用后缀 d 或 D,例如:
double x = 3D;
可在一个表达式中兼用数值整型和浮点型。 在此情况下,整型将转换为浮点型。 根据以下规则计算表达式:
-
如果其中一个浮点类型为 double,则表达式的计算结果为 double 或 bool(在关系表达式或布尔表达式中)。
浮点表达式可以包含下列值集:
-
正零和负零。
-
正无穷和负无穷。
-
非数字值 (NaN)。
-
有限的非零值集。
有关这些值的更多信息,请参见 IEEE 网站上的“IEEE Standard for Binary Floating-Point Arithmetic”(二进制浮点算法的 IEEE 标准)。
在下面的示例中,一个 int、一个 short、一个 float 和一个 double 相加,计算结果为 double 类型。
// 表达式中的混合类型 class MixedTypes { static void Main() { int x = 3; float y = 4.5f; short z = 5; double w = 1.7E+3; // Result of the 2nd argument is a double: Console.WriteLine("The sum is {0}", x + y + z + w); } } // 输出: The sum is 1712.5
bool
可将布尔值赋给 bool 变量。 也可以将计算结果为 bool 类型的表达式赋给 bool 变量。
public class BoolTest { static void Main() { bool b = true; // WriteLine自动将B的值转换为文本。 Console.WriteLine(b); int days = DateTime.Now.DayOfYear; // 将布尔表达式的结果分配给B。 b = (days % 2 == 0); // Branch depending on whether b is true or false. if (b) { Console.WriteLine("days is an even number"); } else { Console.WriteLine("days is an odd number"); } } } /* 输出: True days is an <even/odd> number */
bool 变量的默认值为 false。 bool? 变量的默认值为 null。
在 C++ 中,bool 类型的值可转换为 int 类型的值;也就是说,false 等效于零值,而 true 等效于非零值。 在 C# 中,不存在 bool 类型与其他类型之间的相互转换。 例如,下面的 if 语句在 C# 中无效:
int x = 123; // if (x) // 错误 { Console.Write("The value of x is nonzero."); }
若要测试 int 类型的变量,必须将该变量与一个值(例如零)进行显式比较,如下所示:
if (x != 0) // The C# way { Console.Write("The value of x is nonzero."); }
在此例中,您从键盘输入一个字符,然后程序检查输入的字符是否是一个字母。 如果字符是一个字母,则程序检查它是大写还是小写。 这些检查是使用 IsLetter 和 IsLower(两者均返回 bool 类型)来执行的:
public class BoolKeyTest { static void Main() { Console.Write("Enter a character: "); char c = (char)Console.Read(); if (Char.IsLetter(c)) { if (Char.IsLower(c)) { Console.WriteLine("The character is lowercase."); } else { Console.WriteLine("The character is uppercase."); } } else { Console.WriteLine("Not an alphabetic character."); } } } /* 样本输出: Enter a character: X The character is uppercase. Enter a character: x The character is lowercase. Enter a character: 2 The character is not an alphabetic character. */
char
char 类型的常数可以写成字符、十六进制换码序列或 Unicode 表示形式。 您也可以显式转换整数字符代码。 在下面的示例中,四个 char 变量使用同一字符 X 初始化:
char[] chars = new char[4]; chars[0] = 'X'; // 字符文字 chars[1] = '\x0058'; // 十六进制的 chars[2] = (char)88; // 积分型铸造 chars[3] = '\u0058'; // Unicode foreach (char c in chars) { Console.Write(c + " "); } // 输出: X X X X
char 可以隐式转换为 ushort、int、uint、long、ulong、float、double 或 decimal。 但是,不存在从其他类型到 char 类型的隐式转换。
System.Char 类型提供几个处理 char 值的静态方法。
decimal
如果希望实数被视为 decimal 类型,请使用后缀 m 或 M,例如:
decimal myMoney = 300.5m;
如果没有后缀 m,数字将被视为 double 类型,从而导致编译器错误。
整型被隐式转换为 decimal,其计算结果为 decimal。 因此,可以用整数初始化十进制变量而不使用后缀,如下所示:
decimal myMoney = 300;
在浮点型和 decimal 类型之间不存在隐式转换;因此,必须使用强制转换在这两种类型之间进行转换。 例如:
decimal myMoney = 99.9m; double x = (double)myMoney; myMoney = (decimal)x;
还可以在同一表达式中混合使用 decimal 和数值整型。 但是,不进行强制转换就混合使用 decimal 和浮点型将导致编译错误。
可以通过使用 String.Format 方法或 Console.Write 方法(它调用 String.Format())来格式化结果。 货币格式是使用标准货币格式字符串“C”或“c”指定的,如本文后面的第二个示例所示。 有关 String.Format 方法的更多信息,请参见 String.Format。
在此例中,同一个表达式中混合使用了 decimal 和 int。 计算结果为 decimal 类型。
下面的示例通过尝试添加 二进制文件 和 decimal 变量会导致编译器错误。
double dub = 9; // 下面的行导致一个错误,读取“运算符”+不能应用于 // “双”和“小数”类型的操作数 Console.WriteLine(dec + dub); // 可以通过使用操作数的显式铸造来修复错误。 Console.WriteLine(dec + (decimal)dub); Console.WriteLine((double)dec + dub);
其结果是导致以下错误:
运算符“+”不能应用于“双”和“十进制”类型的操作数。
public class TestDecimal { static void Main() { decimal d = 9.1m; int y = 3; Console.WriteLine(d + y); // 结果转换为十进制 } } // Output: 12.1
在此例中,使用了货币格式字符串来设置输出格式。 注意:其中 x 被舍入,因为其小数点位置超出了 $0.99。 而表示最大精确位数的变量 y 严格按照正确的格式显示。
public class TestDecimalFormat { static void Main() { decimal x = 0.999m; decimal y = 9999999999999999999999999999m; Console.WriteLine("My amount = {0:C}", x); Console.WriteLine("Your amount = {0:C}", y); } } /* 输出: My amount = $1.00 Your amount = $9,999,999,999,999,999,999,999,999,999.00 */
object
object 类型在 .NET Framework 中是 Object 的别名。 在 C# 的统一类型系统中,所有类型(预定义类型、用户定义类型、引用类型和值类型)都是直接或间接从 Object 继承的。 可以将任何类型的值赋给 object 类型的变量。 将值类型的变量转换为对象的过程称为“装箱”。 将对象类型的变量转换为值类型的过程称为“取消装箱”。 有关更多信息,请参见装箱和取消装箱。
下面的示例演示了 object 类型的变量如何接受任何数据类型的值,以及 object 类型的变量如何在 .NET Framework 中使用 Object 的方法。
class ObjectTest { public int i = 10; } class MainClass2 { static void Main() { object a; a = 1; Console.WriteLine(a); Console.WriteLine(a.GetType()); Console.WriteLine(a.ToString()); a = new ObjectTest(); ObjectTest classRef; classRef = (ObjectTest)a; Console.WriteLine(classRef.i); } } /* 输出 1 System.Int32 1 * 10 */
string
string 类型表示一个字符序列(零个或更多 Unicode 字符)。 string 是 .NET Framework 中 String 的别名。
尽管 string 是引用类型,但定义相等运算符(== 和 !=)是为了比较 string 对象(而不是引用)的值。 这使得对字符串相等性的测试更为直观。 例如:
string a = "hello"; string b = "h"; // 追加到“B”的内容 b += "ello"; Console.WriteLine(a == b); Console.WriteLine((object)a == (object)b);
这将先显示“True”,然后显示“False”,因为字符串的内容是相同的,但是 a 和 b 引用的不是同一个字符串实例。
+ 运算符用于连接字符串:
string a = "good " + "morning";
这将创建一个包含“good morning”的字符串对象。
字符串是不可变的,即:字符串对象在创建后,尽管从语法上看您似乎可以更改其内容,但事实上并不可行。 例如,编写此代码时,编译器实际上会创建一个新字符串对象来保存新的字符序列,且新对象将赋给 b。 然后字符串“h”将适宜于垃圾回收。
string b = "h"; b += "ello";
[] 运算符可以用于对 string 的各个字符的只读访问。
string str = "test"; char x = str[2]; // x = 's';
字符串为 string 类型并可写成两种形式,即用引号引起来和用 @ 引起来。 用引号引起来的字符串括在双引号 (") 内:
"good morning" // 字符串文字
字符串文本可包含任何字符。 包括转义序列。 下面的示例使用转义序列 \\ 来表示反斜杠,使用 \u0066 来表示字母 f,使用 \n 来表示换行符。
string a = "\\\u0066\n"; Console.WriteLine(a);
说明 |
---|
转义码 \udddd(其中 dddd 是一个四位数)表示 Unicode 字符 U+dddd。 此外还识别 8 位 Unicode 转义码: \Udddddddd。 |
原义字符串以 @ 开头并且也用双引号引起来。 例如:
@"good morning" // 字符串文字
原义字符串的优势在于不 处理转义序列,因此很容易写入,例如完全限定的文件名就是原义字符串:
@"c:\Docs\Source\a.txt" // 而不是 "c:\\Docs\\Source\\a.txt"
若要在一个用 @ 引起来的字符串中包括一个双引号,请使用两对双引号:
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
@ 符号的另一种用法是使用作为 C# 关键字的被引用的 (/reference) 标识符。
有关 C# 中字符串的更多信息,请参见字符串(C# 编程指南)。
class SimpleStringTest { static void Main() { string a = "\u0068ello "; string b = "world"; Console.WriteLine( a + b ); Console.WriteLine( a + b == "Hello World" ); // == 执行区分大小写的比较 } } /* 输出: hello world False */