• 1. C#数据类型 (续) 第2章C#程序设计
  • 2. String表示字符串类型,是.NET类库中做常用类之一,它将一组字符视为一个整体进行处理。2.2 引用类型——字符串类型string s1=“”; //定义一个空字符串 string s2=“a” //使用双引号定义字符串常量 s1=“Hello”; 思考: 空字符串和null的区别。 注意: char c=‘a’; 和 string s=“a”;
  • 3. 1. 字符串和字符数组 字符串是对一组字符的封装,用法类似字符数组,但String类的索引操作是只读的。 string s1=“Hello”; char c=s1[1]; //c1=‘e’ s1[2]=’X‘; //错误,不能修改字符串中的字符 基于字符数组可构造字符串,使用字符串的ToCharArray方法可得到对应的字符数组。 char[] chs={‘M’,’i’,’c’,’r’,’o’,’s’,’o’,’f’,’t’}; string s=new string(chs); //s=“Microsoft” char[] chs1=s.ToCharArray(); //将字符串全部转换为字符数组2.2 引用类型——字符串类型
  • 4. 1. 字符串和字符数组 在字符串中查找字符使用IndexOf和LastIndexOf方法,返回指定字符首次(或最后一次)出现的位置,未找到则返回-1。如: string s=“中国中信银行”; int pos=s.IndexOf(‘中’); //pos=0 pos=s.LastIndexOf(‘中’); //pos=2 pos=s.IndexOf(‘A’); //pos=-1 pos=s.IndexOf(‘中’,1); //pos=2 pos=s.IndexOf(‘中’,0,2); //pos=02.2 引用类型——字符串类型
  • 5. 1. 字符串和字符数组 IndexOfAny和LastIndexAny方法提供了更为强大的字符查找功能,其查找对象是指定字符数组中的任意字符。返回指定字符首次(或最后一次)在数组中出现的位置,未找到则返回-1。如下列注册页面: 2.2 引用类型——字符串类型要求: 用户名必须以字母开头,且不能含有非法字符@、#、$、%、!、?
  • 6. 2.2 引用类型——字符串类型private void btnConfirm_Click(object sender, EventArgs e) { char[] illChars = { '@','#','$','%','!','?','&'}; string userName = tbUserName.Text.Trim(); if (userName.Length == 0 || !char.IsLetter(userName[0])) MessageBox.Show("错误! 用户名必须以字母开头"); else if (userName.IndexOfAny(illChars) >= 0) MessageBox.Show("错误!用户名中含有非法字符"); else { MessageBox.Show("注册成功!"); this.Close(); } }
  • 7. 2. 子串操作 字符串中任意一段连续的字符称为该字符串的子串。IndexOf和LastIndexOf方法也可用于查找指定的子串,返回子串的首字符位置。 string s=“Microsoft”; int pos=s.IndexOf(“Mic”); //pos=0 pos=s.IndexOf(“Mic”,2); //pos=-1 pos=s.LastIndexOf(“soft”); //pos=5;2.2 引用类型——字符串类型
  • 8. 2. 子串操作 StartsWith方法和EndWith方法分别用于判断字符串是否以指定的子串开始和结束。Contains方法则判断字符串中是否包含指定的子串。 string s=“Microsoft”; bool b=s.StartWith(“Mic”); //b=true b=s.StartWith(“soft”); //b=false b=s.EndWith(“soft”); //b=true b=s.Contains(“soft”); //b=true2.2 引用类型——字符串类型
  • 9. 2. 子串操作 Substring方法用于从字符串中截取一个子串。 string s=“中国中信银行”; string s1=s.Substring(2); //s1=“中信银行” string s2=s.Substring(1,3); //s2=“国中信”2.2 引用类型——字符串类型Remove方法用于从字符串中删除指定子串。 string s=“清华大学出版社”; string s1=s.Remove(4); //s1=“清华大学” string s2=s.Remove(2,2); //s2=“清华出版社”
  • 10. 2. 子串操作 Insert方法用于在字符串中指定位置插入一个子串。 string s=“中信银行分行” string s1=s.Insert(4,”济南”); //s1=“中信银行济南分行”2.2 引用类型——字符串类型RePlace方法用于字符或子串替换。常用文档中错误文本替换,如将拼写错误的成语或英文单词进行替换。
  • 11. 3. 格式化和解析 任何对象都可以通过从Object类中继承的ToString方法得到其字符串表示。String类提供的Format方法用于通过指定的参数来格式化一个字符串,其参数形式与Console类的WriteLine方法参数类似。如: int x=2,y=4; string s=String.Format(“{0}月{1}日”,x,y); //s=“2月4日” s=String.Format(“{0}*{1}={2}”,x,y,x*y); //s=“2*4=8” 提示:默认情况下,Format方法对每个参数对象调用其ToString方法,然后将各项内容合并到结果中。2.2 引用类型——字符串类型
  • 12. 3. 格式化和解析 对于数值类型的参数,还可以指定参数对象的标准输出格式。 string s=String.Format(“{0:C}元”,12.5); //s=“¥12.50元” string s=String.Format(“{0:C4}元”,12.5); //s=“¥12.5000元” 提示:其他常用的标准格式说明符还包括D(十进制格式)、E(指数格式)、F(浮点格式)、N(数字格式)、P(百分比格式)和X(十六进制格式)。2.2 引用类型——字符串类型
  • 13. 3. 格式化和解析 字符串解析是从字符串出发构造其他类型的对象,要将字符串转化为整数、实数、布尔登值类型的变量,可使用这些类型提供的字符串解析方法Parse。如: bool b=bool.Parse(“True”); int x=int.Parse(“3”); double d=double.Parse(Console.ReadLine()); 提示: 如果被解析的字符串格式不正确,程序就会发生异常。2.2 引用类型——字符串类型
  • 14. 接口是C#中提供的一种抽象数据类型,它描述的是一种”契约” ,其中约定了服务方需要提供的一组功能。如: interface IPay { bool Pay(decimal price); } 接口定义使用关键字interface,接口中定义的方法不提供实现代码,它描述的是“能做什么”,但不关心“怎样做”,对接口不能创建对象。下面的代码是错误的。 IPay p1=new IPay(); 2.2 引用类型——接口
  • 15. C#语言中的相容数据类型之间可以进行转换其中包括: 数值(字符)转换 枚举转换 引用转换 装箱和拆箱转换2.3 类型转换
  • 16. 隐式转换是系统默认的,不需要加以声明就可以直接进行转换。而显式转换又叫强制类型转换,需要明确指定转换的类型。隐式转换(implicit) 显式转换(explicit)从转换的声明方式分,每种转换有可分为:2.3 类型转换
  • 17. 数值转换是指在各种整数、实数以及字符类型之间进行的转换。2.3 类型转换——数值转换低精度数值类型高精度数值类型隐式转换显式转换无符号数值类型有符号数值类型显式转换char类型数值类型隐式转换显式转换
  • 18. 源类型可隐式转换到无信息丢失精度可能会降低byte ushort、short、uint、int、ulong、long、float、double、decimalsbyteshort、int、long、float、double、decimalshortint、long、float、double、decimalushort uint、int、ulong、long、float、double、decimalintlong、double、decimalfloatuintlong、ulong、double、decimalfloatlongdecimal float、doubleulongdecimalfloat、double floatdoublechar ushort、uint、int、ulong、long、float、double、decimal2.3 类型转换——数值转换
  • 19. 源类型可显式转换到bytesbyte、charsbytebyte、ushort、uint、ulong、charshortbyte、sbyte、ushort、charushortbyte、sbyte、short、charintbyte、sbyte、short、ushort、uint、charunitbyte、sbyte、short、ushort、int、charlongbyte、sbyte、short、ushort、int、uint、ulong、charulongbyte、sbyte、short、ushort、int、uint、long、chardecimalbyte、sbyte、short、ushort、int、uint、long、ulong、charfloatbyte、sbyte、short、ushort、int、uint、long、ulong、chardoublebyte、sbyte、short、ushort、int、uint、long、ulong、charcharbyte、sbyte、short2.3 类型转换——数值转换
  • 20. 隐式转换转化形式:var1 = var2long l; int i=10; l=i; //隐式转换 Console.WriteLine(“l={0}, i={1}”,l,i);输出:2.3 类型转换——数值转换l=10, i=10
  • 21. 显式转换转化形式:var1 = (NewType)var2 int i; long l=10; //隐式转换 i=(int)l; //显式转换 Console.WriteLine(“l={0}, i={1}”,l,i);输出:2.3 类型转换——数值转换l=10, i=10
  • 22. 显式转换转化形式:var1 = (NewType)var2 2.3 类型转换——数值转换Console.WriteLine(“b={0}, s={1}”, b, s);byte b;short s= 300;b =(byte) s; //显式转换 输出:b=44, s=300运行结果因溢出而出错!
  • 23. 显式转换var1 = (NewType)var2Console.WriteLine(“b={0}, s={1}”, b, s);byte b;short s= 300;b =checked((byte) s); //显式转换 增加溢出检查表达式checked,运行时发生溢出错误2.3 类型转换——数值转换
  • 24. 显式转换2.3 类型转换——数值转换
  • 25. 显式转换var1 = (NewType)var2Console.WriteLine(“b={0}, s={1}”, b, s);byte b;short s= 300;b =unchecked((byte) s); //显式转换 增加溢出检查表达式unchecked,不对表达式进行溢出检查 输出: //运行结果因溢出而出错!2.3 类型转换——数值转换b=44, s=300
  • 26. using System; namespace P2_10 { class Program { static void Main() { long l = long.MinValue; Console.WriteLine("l={0}",l); double d = l; //隐式转换 Console.WriteLine("d={0}",d); l = (long)d; //显式转换 Console.WriteLine("l={0}",l); } } }2.3 类型转换——数值转换
  • 27. 低精度向高精度转换通常是安全的,但有时候也会发生信息丢失,不是指数值的大小改变,而是数值的精度会降低2.3 类型转换——数值转换
  • 28. using System; namespace P2_10 { class Program { static void Main() { int i= int.MaxValue; Console.WriteLine(i); short s = (short)i; //显式转换 Console.WriteLine(s); double d=double.MaxValue; Console.WriteLine(d); float f=(float)d; //显式转换 Console.WriteLine(f); } } }2.3 类型转换——数值转换
  • 29. 从高精度向低精度转换不能保证总是成功,而且可能发生信息丢失。2.3 类型转换——数值转换
  • 30. char类型与ushort类型存在对应关系。char ch=‘A’; ushort s=ch; //隐式转换,得到字符的十进制整数编码 int i=ch; //转换类型? Console.WriteLine(“ch={0}, s={1}, i={2}”,ch,s,i); s=97; ch=(char)s; //转换类型? Console.WriteLine(“ch={0}, s={1}”,ch,s);输出: ch=A, s=65, i=65 ch=a, s=972.3 类型转换——字符转换ch=A, s=65, i=65 ch=a, s=97
  • 31. char类型与ushort类型存在对应关系。int x=(int)’A’; //如何转换? char ch=(char)100; //如何转换? 2.3 类型转换——字符转换char —> ushort—>int 隐式转换int —> ushort—>char 显式转换
  • 32. 枚举转换 隐式转换:把0直接赋给枚举类型的变量 显式转换 整数类型(包括字符类型)和实数类型<—>枚举类型 枚举类型<—>枚举类型2.3 类型转换——枚举转换
  • 33. using System; namespace P2_11 { class Program { static void Main() { Weekday w1=0; //隐式转换 Console.WriteLine(w1); //输出? Weekday w2=(Weekday)6; //显式转换 不能写成:day=6; Console.WriteLine(w2); //输出? w2=w2+1; int x=(int)w2; //显式转换 Console.WriteLine(x); //输出? } } enum Weekday { Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday } }2.3 类型转换——枚举转换
  • 34. Convert类位于System命名空间中,主要用于将一个值类型转换成另一个值类型,其语法格式: public sealed class ConvertConvert类中用于实现类型转换的方法都是静态方法(静态方法只能通过类名访问,不能通过类的实例访问),可通过 ”Convert.方法名(参数)“使用,常见方法如表所示:2.3 类型转换——Convert类
  • 35. 方法说明Convert.ToBoolean(var)var转换为boolConvert.ToByte(var)var转换为byteConvert.ToChar(var)var转换为charConvert.ToDateTime(var)var转换为DateTimeConvert.ToDecimal(var)var转换为DecimalConvert.ToDouble(var)var转换为DoubleConvert.ToInt16(var)var转换为shortConvert.ToInt32(var)var转换为intConvert.ToInt64(var)var转换为longConvert.ToSByte(var)var转换为sbyteConvert.ToSingle(var)var转换为float2.3 类型转换——Convert类
  • 36. 方法说明Convert.ToString(var)var转换为stringConvert.ToUInt16(var)var转换为ushortConvert.ToUInt32(var)var转换为uintConvert.ToUInt64(var)var转换为ulong2.3 类型转换——Convert类
  • 37. int i; string str = “123”; i = Convert.ToInt32(str ); Console.WriteLine(“str={0}, i={1}”, str, i);执行后输出:2.3 类型转换——Convert类str=123, i=123
  • 38. int i; string str = “123dd”; i = Convert.ToInt32(str ); Console.WriteLine(“str={0}, i={1}”, str, i);如果参数格式不符合要求,则引发参数格式异常(FormatException)。2.3 类型转换——Convert类
  • 39. 2.3 类型转换——Convert类
  • 40. C#中的很多类型(特别是值类型)都定义了字符串解析的基本方法,这个方法就是Parse方法。如:Boolean.Parse 方法 的定义如下: public static bool Parse( string value )Parse方法是静态的,且返回值类型就是该方法所属的类型。Parse方法只有一个String类型的参数如:Int32.Parse 方法的定义如下: public static int Parse( string s )2.3 类型转换——Parse方法
  • 41. int a, b, sum; Console.Write("a="); a = int.Parse(Console.ReadLine()); Console.Write("b="); b = int.Parse(Console.ReadLine()); sum = a + b; Console.WriteLine(“a+b={0}”, sum); 2.3 类型转换——Parse方法 运行后,如果从控制台输入25和30,则应输出结果是什么?a=25 b=30 a+b=55思考:如果运行后,如果从控制台输入2.5和30,则会出现什么情况?
  • 42. bool b=bool.Parse("True"); int i=int.Parse("5"); double d=double.Parse("2.5"); DateTime dt=DateTime.Parse("2013-9-25"); Console.WriteLine("b={0}, i={1}, d={2}, dt={3}", b, i, d, dt); 2.3 类型转换——Parse方法 运行后,输出结果是什么?b=True, i=5, d=2.5 dt=2013-9-25 0:00:00
  • 43. TryParse是Parse方法的替代方法,通常有两个参数,一个表示要解析的字符串,而另一个是输出参数,用于存放解析结果;方法返回一个布尔值,用于指示解析是否成功。 int x,y; int.TryParse(“5“,out x); //返回? x=? int.TryParse(“2.5”,out y); //返回? y=? double d; double.TryParse(“2.5”,out d); //返回? d=? DateTime dt1,dt2; DateTime.TryParse(“2013-9-25”,out dt1); //返回? DateTime.TryParse(“2013-9-31”,out dt2); //返回? Console.WriteLine(“x={0}, y={1}, d={2}, dt1={3},dt2={4}", x, y, d, dt1, dt2);2.3 类型转换——TryParse方法 x=5, y=0, d=2.5 dt1=2013-9-25 0:00:00, dt2=0001-1-1 0:00:00
  • 44. TryParse可以提高程序的可靠性。 int x; Console.Write(“请输入整数x的值:”); while( ! int.TryParse(Console.ReadLine(),out x)) Console.WriteLine(“输入格式不正确!请重新输入x的值”); …… 用户也可以为自定义的类型提供Parse和TryParse方法。2.3 类型转换——TryParse方法
  • 45. 引用转换包括类之间、接口之间、类与接口之间、委托之间、数组之间的类型转换。 所有的引用转换都可以视为类之间以及类和接口之间的转换。(为什么?) 任何引用转换都不会修改对象的内容,也不会有信息的丢失。(为什么?) 引用转换也有隐式引用转换和显式引用转换两种。2.3 类型转换——引用转换
  • 46. 引用类型引用类型 引用转换的一条基本原则: 派生类基类(含接口):隐式转换 基类(含接口)派生类:显式转换2.3 类型转换——引用转换 演示:引用类型之间转换P2_12.cs空引用值Null可赋给任何一种引用类型的变量。
  • 47. 引用类型引用类型 Object类型是所有其他类型的基类,故任何引用类型的变量都可以转换为Object类型,反之则要进行显式转换2.3 类型转换——引用转换 BankCard card2=new BankCard(){money=800}; Object obj=card2; //隐式转换 IPay i2=(IPay)obj; //显式转换 Account acc2=(Account)obj; //显式转换
  • 48. 引用类型引用类型 C#规定,值类型的数组之间不能进行转换,而在引用类型的数组之间进行转换,如数组A1和A2,要求: A1和A2维数相同 A1和A2的数组元素都是引用类型 存在从A1数组元素类型向A2数组元素类型的隐式(或显式)引用转换。 2.3 类型转换——引用转换 思考:可否将一个枚举类型的数组转换为一个整数数组?如果可以,使用的是哪一种转换?
  • 49. 引用类型引用类型2.3 类型转换——引用转换 BankCard[] cards=new BankCard[]{ new BankCard{},new BankCard() }; Account[] accounts=cards; //隐式转换 IPay[] pays=(BankCard[])accounts; //显式转换 accounts=new Account[]{ new BankCard(),new Account() }; pays=(BankCard[])accounts; //错误:显式转换失败
  • 50. int i = 123; object o = i; //装箱可执行隐式或显式转换 int j = (int) o; //拆箱转换必须执行显式转换i: 123oSystem.Int32装箱j: 123System.object123拆箱System.Int32值类型引用类型 值类型引用类型:隐式转换(装箱转换) 引用类型值类型:显式转换(拆箱转换) 2.3 类型转换——引用转换
  • 51. Object o=2.5 //装箱可执行隐式或显式转换 int i=(int)o; //拆箱转换必须执行显式转换 double d = (double) o; oi: 如果被拆箱的Object类型的值为空null,或者与目标值类型冲突,拆箱转换都会失败,引发异常。2.5d: 2.52.3 类型转换——引用转换
  • 52. A. Object o; int i=(int)o; 如果被拆箱的Object类型的值为空null,或者与目标值类型冲突,拆箱转换都会失败,引发异常。以下拆箱转换语句中,正确的有( )? B. Object o=10.5; int i=(int)o; C. Object o=10.5; float f=(float)o; D. Object o=10.5; float f=(float)(double)o; 2.3 类型转换——引用转换 D
  • 53. 本章小结C#中的数据类型分为值类型和引用类型,其中值类型又包括整数、布尔、实数、结构、枚举;引用类型则包括类、接口、委托和数组。这些类型在.NET类库中都有相应定义。值类型的变量总是直接包含自身的数据,而引用类型的变量则指向实际数据的地址。 C#规定,在特定的值类型之间以及引用类型之间可进行隐式或显式的类型转换。而装箱和拆箱转换则在值类型和引用类型之间建立了联系,使得整个C#类型系统成为一个有机的整体,从而能够以面向对象的方式来处理所有数据类型。 除了显式和隐式转换外,C#提供了一些类和方法完成类型之间的转换:Convert类,Parse和TryParse方法。
  • 54. 再见!