C#基础_类型转换

类型转换

  • 为什么需要类型转换
  • 隐式(implicit)类型转换
    • 不丢失精度的转换
    • 子类向父类的转换
    • 装箱
  • 显示(explicit)类型转换
    • 有可能丢失精度(甚至发生错误)的转换,即cast即(T)x
    • 拆箱
    • 使用Convert类
    • ToString方法与各类数据类型的ParseTryparse方法
  • 自定义类型转换操作符

为什么需要类型转换

示例:我们希望用户在命令行输入两个值,然后返回两个值相加的值

	string str1 = Console.ReadLine();//获取一行用户输入的数据
	string str2 = Console.ReadLine();//获取一行用户输入的数据
	Console.WriteLine(str1+str2);//将两个字符串拼接
	//但因为值str1,str2类型为string,所以输出的值为两个字符串拼接的数值

由上面的例子可以看出,因为Console.ReadLine()获取到的数据类型为string类型,我们便得不到我们希望的两个值相加之后的值,而是得到两个拼接的字符串.
这个时候,如果我们希望得到的是两个int数值相加的数,就需要将string类型的值转换为int类型的值,示例如下

	string str1 = Console.ReadLine();//获取一行用户输入的数据
	string str2 = Console.ReadLine();//获取一行用户输入的数据
	int x = Convert.ToInt32(str1);//将用户输入的数据转换为int32类型
	int y = Convert.ToInt32(str2);//将用户输入的数据转换为int32类型
	Console.WriteLine(x+y);//将转换过后的值相加

隐式(implicit)类型转换

隐式类型转换:不用明确的告诉编译器我们要转换的类型

不丢失精度的转换

由高位像低位类型转换,时,不会丢失精度,示例如下

	int x = int.MaxValue; //声明一个int类型的数据
	long y = x;//将刚刚声明的int类型数据赋值给long类型变量
	//这里int类型数据x将会隐式转换为long类型
	Console.WriteLine(x);//值为2147483647
	Console.WriteLine(y);//值为2147483647没有丢失精度
  • 从 sbyte 到 short、int、long、float、double 或 decimal。
  • 从 byte 到 short、ushort、int、uint、long、ulong、float、double 或 decimal。
  • 从 short 到 int、long、float、double 或 decimal。
  • 从 ushort 到 int、uint、long、ulong、float、double 或 decimal。
  • 从 int 到 long、float、double 或 decimal。
  • 从 uint 到 long、ulong、float、double 或 decimal。
  • 从 long 到 float、double 或 decimal。
  • 从 ulong 到 float、double 或 decimal。
  • 从 char 到 ushort、int、uint、long、ulong、float、double 或 decimal。
  • 从 float 到 double。
    从 int、uint、long 或 ulong 到 float 的转换以及从 long 或 ulong 到 double 的转换可能导致精度损失,但决不会影响数值大小。其他的隐式数值转换决不会丢失任何信息。
    不存在向 char 类型的隐式转换,因此其他整型的值不会自动转换为 char 类型。

子类向父类的转换

所以面向对象的语言都支持子类向父类的转换

	class Program
	{
     
	    static void Main(string[] args)
	    {
     
	        Son s;//声明一个类型为Son的变量s
	        s = new Son();//将实例Son的地址交给变量s
	        Father f ;//声明一个类型为Father的变量f
	        f= s;//将引用变量s里面的地址交给f
	        //这里发生了由子类向父类的隐式类型转换,在这里,如果你在s后面接成员访问操作符"."的时候
	        //就能看到s里面所存在的三个方法Grandfathers,Fathers,以及Sons三个自定义方法
	        //而在f后面接成员访问操作符的时候,就只能看到Grandfathers,Fathers两个自定义方法了
	        //这是因为C#规定:当你试图拿一个引用变量取访问它所引用实例的成员的时候,你只能访问到这个变量的类型它所具有的成员
	        //注意是你这个变量的类型,而不是你这个变量所引用的实例的类型
	        //而我们这里f的类型是Father,而Father里面只有Grandfathers,Fathers两个自定义方法了,所以f也就只能访问到这两个方法
	        //下面的Grandfather同理
	        Grandfather g = f;//声明一个Grandfather类型的变量g并将f所引用的实例地址赋值给g
	        //这个时候.在g后面使用成员访问操作符就只能看到Grandfathers一个自定义方法了
	    }
	}
	class Grandfather//创建一个基类
	{
     
	    public void Grandfathers()
	    {
     
	        Console.WriteLine("这是Grandfather");
	    }
	}
	class Father : Grandfather//继承Father 
	{
     
	    public void Fathers()
	    {
     
	        Console.WriteLine("这是Father");
	    }
	}
	class Son : Father//继承Father
	{
     
		//因为Son 继承自Father,而Father又继承自Grandfather,
		//所以Son同时拥有Father中的Fathers方法和Grandfather中的Grandfathers方法
	    public void Sons()
	    {
     
	        Console.WriteLine("这是Son");
	    }
	}

装箱

显示(explicit)类型转换

明确的告诉编译器我们需要转换的数据类型,

有可能丢失精度(甚至发生错误)的转换,即cast即(T)x

示例如下

	Console.WriteLine(ushort.MaxValue);//查看ushort类型的最大值,其值为65535
	uint x = 65536; //给类型为uint的变量赋值为65536(比ushort所能存储的最大值大一)
	/*
		ushort y=x //这里这样直接赋值不行,会出错我们需要cast强制将x转换成ushort然后赋值给y
	*/
	ushort y = (ushort)x;//使用cast,即(T)x的方式强制将x转换为ushort类型,然后赋值给y
	Console.WriteLine(y);//输出y,值为零

上面的例子可以看出,当我们强制给uint类型的变量x转换为ushort类型时,因为低位的二进制00000000已经满了,所以高位的00000001被舍弃,导致ushort丢失精度只获得了低位00000000
下面是需要显示类型转换的

  • 从 sbyte 到 byte、ushort、uint、ulong 或 char。
  • 从 byte 到 sbyte 和 char。
  • 从 short 到 sbyte、byte、ushort、uint、ulong 或 char。
  • 从 ushort 到 sbyte、byte、short 或 char。
  • 从 int 到 sbyte、byte、short、ushort、uint、ulong 或 char。
  • 从 uint 到 sbyte、byte、short、ushort、int 或 char。
  • 从 long 到 sbyte、byte、short、ushort、int、uint、ulong 或 char。
  • 从 ulong 到 sbyte、byte、short、ushort、int、uint、long 或 char。
  • 从 char 到 sbyte、byte 或 short。
  • 从 float 到 sbyte、byte、short、ushort、int、uint、long、ulong、char 或 decimal。
  • 从 double 到 sbyte、byte、short、ushort、int、uint、long、ulong、char、float 或 decimal。
  • 从 decimal 到 sbyte、byte、short、ushort、int、uint、long、ulong、char、float 或 double。

由于显式转换包括所有隐式和显式数值转换,因此总是可以使用强制转换表达式从任何 nnumeric-type 转换为任何其他的
numeric-type。

拆箱

使用Convert类

有些数据类型不能使用cast这种形式来进行转换,比如string转换成int,这个时候我们就需要使用一些工具类来进行转换了
你几乎能使用Convert类来转换任何类型
示例如下

	string a = "12345"; //声明一个string类型的变量并给他赋值12345
	double b = Convert.ToDouble(a);//调用conver类里面的ToDouble方法将变量a的类型转换为doubel,并赋值给变量b
	Console.WriteLine(b);//输出

ToString方法与各类数据类型的ParseTryparse方法

在有些时候,我们也需要将数值类型的数据转化成字符串类型的数据当我们遇到这种情况的时候,就有两种方法来进行转化,一种是上面的调用Console类里面的ToString方法,还有一种就是调用我们数值类型的ToString实例方法
示例如下
先使用wpf创建一个带button和TextBox的窗体

	<Grid>
	    <Grid.RowDefinitions>
	        <RowDefinition Height="Auto">RowDefinition>
	        <RowDefinition Height="auto">RowDefinition>
	        <RowDefinition Height="auto">RowDefinition>
	        <RowDefinition Height="auto">RowDefinition>
	        <RowDefinition Height="auto">RowDefinition>
	        <RowDefinition Height="auto">RowDefinition>
	    Grid.RowDefinitions>
	    <TextBox x:Name="myTextBox1" Grid.Row="0">TextBox>
	    <TextBox x:Name="myTextBox2" Grid.Row="2">TextBox>
	    <TextBox x:Name="myTextBox3" Grid.Row="4">TextBox>
	    <Button x:Name="myButton1" Content="Click Me1!" Grid.Row="1">Button>
	    <Button x:Name="myButton2" Content="Click Me2!" Grid.Row="3" >Button>
	    <Button x:Name="myButton3" Content="Click Me3!" Grid.Row="5">Button>
	Grid>
	public MainWindow()
	       {
     
	           InitializeComponent();
	           this.myButton1.Click += myButton_Click1;
	           this.myButton2.Click += delegate (object sender, RoutedEventArgs e)
	       {
     
	               double x = double.Parse(this.myTextBox1.Text);
	               double y = double.Parse(this.myTextBox2.Text);
	               //parse的缺点,parse只能解析正确的字符串格式类型
	               double result = x + y;
	               this.myTextBox3.Text = result.ToString();
	           };
	           this.myButton3.Click += (a, b) =>
	           {
     
	               double x = System.Convert.ToDouble(this.myTextBox1.Text);
	               double y = System.Convert.ToDouble(this.myTextBox2.Text);
	               double result = x + y;
	               this.myTextBox3.Text = result.ToString();
	           };
	
	       }
	       private void myButton_Click1(object sender, RoutedEventArgs e)
	       {
     
	           double x = System.Convert.ToDouble(this.myTextBox1.Text);
	           double y = System.Convert.ToDouble(this.myTextBox2.Text);
	           double result = x + y;
	           this.myTextBox3.Text = System.Convert.ToString(result);
	       }

自定义类型转换操作符

	class Program
	   {
     
	       static void Main(string[] args)
	       {
     
	           YearsOld yearsOld = new YearsOld();//创建YearsOld类的实例
	           yearsOld.Age = 3600;//给YearsOld 类型属性Age赋值
	           Koshi zhangJiao = (Koshi)yearsOld;//使用(T)x即cast转换
	           //编译器报错,无法将类型Console1.yearsOld转换为Console1.Koshi
	       }
	   }
	   class YearsOld //创建一个类,并创建int类型属性Age
	   {
     
	       public int Age;
	   }
	   class Koshi //创建一个类,并创建int类型属性Age
	   {
     
	       public int Age;
	   }

如上实例,这个时候就需要我们自定义类型转换操作符

class Program
    {
     
        static void Main(string[] args)
        {
     
            YearsOld yearsOld = new YearsOld();
            yearsOld.Age = 3600;
            Koshi zhangJiao = (Koshi)yearsOld;
            Console.WriteLine(zhangJiao.Age);
        }//Koshi
    }
    class YearsOld
    {
     
        public int Age;
        //定义自定义类型转换操作符需要的四个修饰符
        //public 公共的
        //static静态的
        //explicit 显示类型转换
        //operator 运算符
        如果我们把前面的修饰符都忽略掉的话,Koshi(YearsOld yearsOld){},
        是不是和Koshi的构造器一样?,,显式类型转换操作符是一个目标类型的实例构造器,只不过它不是写在目标类型里面,而是写在被转换的数据类型里面
        //
        //目标类型 Koshi 被操作的类型YearsOld 被操作变量yearsOld
        public static explicit operator Koshi(YearsOld yearsOld) {
     
            Koshi k = new Koshi();//实例化Koshi
            k.Age = yearsOld.Age / 60;//定义Koshi的Age属性等于yearsOld的60个Age属性
            return k;//输出转换好的数据
        }
    }
    class Koshi
    {
     
        public int Age;
    }

显式自定义类型转换操作符已经写好了,那隐式的呢?
隐式的和显式的没很大区别,格式一样,只是要把修饰符explicit改为implicit
示例如下:

class Program
    {
     
        static void Main(string[] args)
        {
     
            YearsOld yearsOld = new YearsOld();
            yearsOld.Age = 3600;
            Koshi zhangJiao =yearsOld;//因为是隐式的,所以这里就不需要使用(T)x方式来转换了
            Console.WriteLine(zhangJiao.Age);
        }//Koshi
    }
    class YearsOld
    {
     
        public int Age;
        //将修饰符explicit 改为implicit 就好了
        public static implicit operator Koshi(YearsOld yearsOld) {
     
            Koshi k = new Koshi();
            k.Age = yearsOld.Age / 60;
            return k;
        }
    }
    class Koshi
    {
     
        public int Age;
    }

你可能感兴趣的:(C#,c#)