一、C#中的变量和常量
C#中用于定义常量的方式有两种一个使用const关键字,一个是用readonly关键字。使用const定义的常量叫静态常量(compile-time constant),用readonly定义的常量叫动态常量(runtime constant)。常量定义 public const float PI=3.14159f; 常量PI对于所有的类对象而言都是一致的,要访问该字段可以直接用格式:类.PI进行取值,不需要实例化,类似于一个类的静态字段。而动态常量的定义为 public readonly float NUM,变量NUM可以看做一个动态的常量,可以在类的定义字段赋值或者在类的构造函数函数中赋值。比如可以定义:public readonly float NUM = 20.2F。
来看下面的例子
class Program { static void Main(string[] args) { float pi = Constant.PI; //通过类型取值,和静态变量类似,但是常量是readonly的,不能赋值 float r = 10.2f; float D = 2 * pi * r; Console.WriteLine(D); Constant constant = new Constant(); Console.WriteLine( constant.NUM); //通过实例取值,NUM在构造函数中定义的 Console.WriteLine(constant.NUM1); //通过实例取值,NUM1是在字段的定义的 Console.Read(); } } class Constant { public const float PI = 3.1415926F; public readonly int NUM1 = 10; public readonly int NUM; public Constant() { NUM = 12; } }
二、c#变量数据类型
变量的数据类型包括预定义的数据类型和自定义的数据类型,自定义的数据类型包括数组、枚举、结构和类,而预定义的数据类型如下表所示:
类型 |
描述 |
范围/精度 |
例子 |
||
object |
所有其它类型的最根本的基础类型 |
object o = null; |
|||
string |
字符串类型,一个字符串是一个Unicode字符序列 |
string s= "Hello"; |
|||
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; |
下面程序对数据类型的长度作一个小测试,a,b为整形,c为长整形,d为字符型,e为byte,f为整形。获取整数a 在堆栈中的地址 p =&a,同样可以获取b,c ,d,e,f的地址&b,&c,&d,&e,&f。
class Program { unsafe static void Main(string[] args) { int a = 100; int b = 100; long c = 1200; char d = 'b'; byte e = 10; int f = 20; int* p = &a; //获取整数a的地址 Console.WriteLine((int)&a); Console.WriteLine((int)&b); Console.WriteLine((int)&c); Console.WriteLine((int)&d); Console.WriteLine((int)&e); Console.WriteLine((int)&f); //获取a地址之下一个地址的值(32位),也即是b的地址 Console.WriteLine(*(p - 1)); //获取c的地址,因为c是long类型所以需p-3 Console.WriteLine(*(p - 3)); //获取d的地址,'b'的ASCII码是98 Console.WriteLine(*(p - 4)); Console.WriteLine(sizeof(sbyte)); Console.WriteLine(sizeof(long)); Console.ReadKey(); } }
数据a,b,c,d,e,f分别压入栈中,从图中可以看出他们在内存中的地址,用&a-&b就可算出b的数据长度。c为long占8个字节,其高位的4字节地址中的数据为0,其低位4字节地址中的数为1200,d虽然只占用2个字节,但在类存分配中已4字节为最小单元的情况下(对32位版本而言)还是分配了4个字节,同理内存为e分配了4个字节,实际上它只用了1个字节。
下面,我重点介绍一下其中的几种预定义的数据类型:
float数据类型
float类型数据的位构成:
1bit(符号位) |
8bits(指数位) |
23bits(尾数位) |
Float表示一个有32位的浮点数,其中第一位为符号位,后面8位为幂指数,再其后23位为尾数部分。幂指数的范围为(2-127-2128),表示的数据范围为-3.40E+38 ~ +3.40E+38。而尾数为223=8388608,意味着最多可以有七位的有效位,所以表示float的精度为7位。
可以根据系统自动获取数据范围
float f = float.maxvalue;
float f = float.minvalue;
double类型
double数据类型的位构成:
1bit(符号位) |
11bits(指数位) |
52bits(尾数位) |
Double表示一个64位的双精度数,其中第一位为符号位,后面11位为指数为,再其后为52位尾数部分。指数的范围为(2-1023-21024),表示的数据范围为-1.79E+308 ~ +1.79E+308,尾数为252 = 4503599627370496,意味着最多可以有十六位的有效位,所以表示double的精度为16位。
所以说浮点数的精度由尾数的位数决定,而范围由指数的位数决定。
Bool result = Float.IsNaN(0/0f) ;
判断result的结果是否为一个数字 NaN ( not a number)
Bool result = Float.IsInfinity(10.2f/0f); //判断是否为无穷大
Bool result = Float.IsNegativeInfinity(-20.0f/0); //判断是否为负无穷大
Bool result = Float.IsPositiveInfinity(20.0f/0); //判断是否为正无穷大
Int数据类型
Int 赋值
long l = 200;
int i = l; //直接赋值,系统排出错误,因为l的取值范围要大于i的取值范围,所以需要显示的类型转换
int I = (int)l;
short s= 200;
int I = s; //直接赋值不会出错,系统可以将short类型的s转化为l,
因此将一个取值范围大的数据类型转化为一个取值范围较小的数据类型需要显式地转化,相反讲一个范围较小的数据类型转化为一个取值范围较大的数据系统可以隐式的进行转化。
获取Int数据类型的最大最小值
Int.maxvalue;
Int.minvalue;
Int.parse(“200”)数据转换,将字符串参数转化为整数,但是此种方式不是一种安全的数据转化方式。
如:int.parse(“12x”),系统肯定出错,因为不能成功将字符串"12x"转化为一个整数,在系统运行的时候一定会抛出Exception;但是Int还提供一种安全的转化方式,可以使用Int.tryparse(“sf”,out i)判断转化是否成功,如"sf"不能转化为一个整数,对于不成功的情况我们可以作出相应的处理。
来看下面的例子:
class Program { static void Main(string[] args) { int result; Console.WriteLine("请输入整数"); string inStr = Console.ReadLine(); if (int.TryParse(inStr, out result)) Console.WriteLine("输入的是整数:{0}", result); else MessageBox.Show("输入的不是整数!","出错"); Console.Read(); } }
可以用checked进行溢出校验,也可用unchecked不进行溢出校验,默认情况是不进行校验。
Checked可以用checked函数和checked语句
class Program { static void Main(string[] args) { Console.WriteLine("请输入第一个整数"); int n1 = int.Parse(Console.ReadLine()); Console.WriteLine("请输入第二个整数"); int n2 = int.Parse(Console.ReadLine()); int mut = multiply(n1,n2); Console.Read(); } static int multiply(int x,int y) { int p=0; try { //此处也可用 p = checked(x*y); checked { p = (x * y); } Console.Write(p); } catch (Exception ex) { Console.WriteLine(ex.Message); } return p; } }
Decimal数据类型
Decimal的运算精度很高,可提供如下的算数运算方法:
相加运算 Decimal.Add(decimal d1,decimal d2);
相减运算 Decimal.Subtract(decimal d1,decimal d2);
相乘运算 Decimal.Multiply(decimal d1,decimal d2);
相除运算 Decimal.Divide(decimal d1,decimal d2);
余数运算 Decimal.Remainder(decimal d1,decimal d2)
舍入运算 Decimal.Round(decimal d);
取整运算 Decimal.Truncate(decimal d);
可提供如下的比较运算
Decimal.compare(decimal d1,decimal d2);
Decimal.equals(decimal d1,decimal d2);
Decimal.referenceEquals(decimal d1,decimal d2);
可提供如下的类型转化运算
转化为16位整数 Decimal.toInt16;
转化为32位整数 Decimal.toInt32;
转化为64位整数 Decimal.toInt64;
如果decimal数据类型所提供的方法不够还可以使用自定义的扩展方法,如下例子所示为decimal数据类型扩展一个Power方法(求数据的次方运算):
static class DecExt { public static decimal Power(this decimal baseNum, int p) { decimal result = 1.0M; for (int i = 0; i < p; i++) { result *= baseNum; } return result; } }
class Program
{ static void Main(string[] args) { decimal base1 = 12.2M; decimal x = base1.Power(2); // 对base1的2次方运算 Console.WriteLine(x); Console.Read(); }
}
Char字符类型
Char的常用的静态方法,用来判断某位的字符类型
String pattern = “123abcde”;
Char.IsLetter(pattern,2);
Char.IsNumber(pattern,2);
Char.IsLower(pattern,3);
Char.IsUpper(pattern,3);
Char.IsPunctuation(pattern,3);
Char.IsLetterOrDigit(pattern,3);
(下一节介绍string数据类型)