重庆熊猫 Loading

C#教程 - 数据类型转换(Type Conversion)

更新记录
转载请注明出处。
2022年9月11日 发布。
2022年9月10日 从笔记迁移到博客。

说明

将某个值的类型从A转为B

隐式转换(Implicit type conversion)

说明:

​ 类型兼容情况下才会发生隐式转换

​ 隐式转换发生在类型兼容并且小内存转大内存的情况

以下预定义类型转换会发生隐式转化:

image

显式转化和强制转换(Explicit type conversion)

说明

显式转换 和 强制转换 在程序员需要对自己的行为负责的情况下进行

以下预定义类型转换需要使用显式转换:
image

转换出错将会抛出异常:

转换不成功将抛出InvalidCastException异常

数值转换中溢出将抛出OverflowException异常

显式字符串转为其他类型方法1使用静态方法:Parse

目标类型.Parse(要转换的字符串);

注意:该方法如果转换不成功会抛出异常

注意:如果字符串无法解析为数值将抛出System.FormatException异常

实例:

try
{
    double target1 = double.Parse("3.14159274");
    decimal target2 = decimal.Parse("AAA");
}
catch(FormatException e)
{
    Console.WriteLine(e.Message);
}

显式字符串转为其他类型方法2使用静态方法:TryParse

类型.TryParse(要转换的字符串,out 目标类型变量);

注意:如果转换不成功将赋值给目标类型变量默认值

实例:

double target1;
decimal target2;
double.TryParse("3.14159274",out target1);
decimal.TryParse("3.14159274",out target2);

实例:使用tryParse返回值做条件

int count;
string input = Console.ReadLine(); 
if (int.TryParse(input, out count))
{
  WriteLine($"There are {count} eggs.");
}
else
{
  WriteLine("I could not parse the input.");
}

数值转为十六进制字符串

int i = 16;
Console.WriteLine(i.ToString("x"));

十六进制字符串转为数值

string hexString = "FF";
int number = int.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
Console.WriteLine(number);

字符串转为字符数组

string textString = "Panda66";
char[] charArray = textString.ToCharArray();

强制转换

(目标类型)表达式

实例:

unchecked
{
    byte target = (byte)123123123;
    Console.WriteLine(target);//179
}

转换分类

image

对于自定义类型,用户可以自定义隐式和显式转化

装箱和拆箱(Boxing and Unboxing)

可以使用 装箱 和 拆箱 进行转换,对应中间类型:System.Object、System.ValueType

装箱转换:
image

拆箱转化:
image

装箱后仍然可以获得值的Type类型来确定其真实类型

实例:

object abc = 123;

Console.WriteLine($"{abc.GetType()}"); //System.Int32

注意:装箱和拆箱发生在值类型和引用类型之间,其他类型不可以

//引用转换
object[] a1 = new String[3];
//这是不可以的
object[] a2 = new int[3];  //error

注意:装箱执行的是值复制

int i = 3;
object boxed = i;
i = 5;
Console.WriteLine (boxed);    // 3

数值转换

数值的转换可以是 显式 也可以是 隐式 的
image

占用内存较小的类型 可以 隐式转换 为 占用内存较大的类型
image

对于 占用内存较大的类型 转为 占用内存较小的类型 需要使用 显式转换

注意:Char类型与数值进行转换需要使用强制转换

数值转换的几种方法(Numbers Conversions)
image

检测数值溢出

数值转换会出现溢出的情况,使用checked运算符可以处理溢出情况

如果转换代码不使用checked检测,则溢出不会被处理,代码继续执行

如果转换代码使用checked检测,存在溢出就抛出OverflowException异常

默认情况下是不进行检测溢出的

使用unchecked运算符会忽略溢出检查

使用方法:

checked(表达式);
unchecked(表达式);

除了这种用法,还可以使用大括号语法:

checked
{
    bool test1 = Convert.ToBoolean("true");
    bool test2 = Convert.ToBoolean(0);
    bool test3 = Convert.ToBoolean(-1);
}

还可以进行嵌套:

checked
{
    bool test1 = Convert.ToBoolean("true");
    bool test2 = Convert.ToBoolean(0);
    unchecked
    {
        bool test3 = Convert.ToBoolean(-1);
    }
}

注意:checked只能用于整数类型,用于float、double类型无效

注意:checked对decimal无效,因为decimal类型总是会进行类型溢出检查

is运算符

默认情况下,转换不成功将抛出InvalidCastException异常,使用is运算符检测,可以避免抛出异常

使用格式:

对象 is 类/接口
Tom is Person //返回一个boolean值

is运算符只能用于引用转换、装箱转换、拆箱转换,不可以用于用户自定义转换

is运算符和C#模式匹配(C# 7可用)

即在is匹配时声明变量

实例1:

string test = "Panda666.com";
if(test is string result)
{
    Console.WriteLine(result);
}

实例2:

string test = "Panda666.com";
if(test is string result && result == "Panda666.com")
{
    Console.WriteLine(result);
}

as运算符

as运算符和强制转换类似,但不抛出异常

如果转换失败,返回null,而不是抛出异常

as运算符常用于对象向上和向下转换

使用格式:

对象 as 类/接口
Tom as Person //返回对象或null

as运算符转换后使用前,记得检测是否为null

as运算符只能用于引用转换和装箱转换,不可以用于自定义转换或转为值类的转换

值类型有意思的地方

C#的所有值类型均隐式派生自System.ValueType,而System.ValueType直接派生于System.Object

即System.ValueType本身是一个类类型,而不是值类型

其关键在于ValueType重写Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较

引用类型转换(Reference Conversions)

引用类型转换说明

分为向上(Upcasting)转换 和 向下(Downcasting)转换

Implicitly upcast to a base class reference

Explicitly downcast to a subclass reference

注意:如果向下转换失败,会抛出InvalidCastException异常

向上(Upcasting)转换

向上(Upcasting)转换是指子类转为父类的引用

这是隐式(Implicitly upcast)转换的

实例:

using System;
namespace ConsoleApp1
{
    /// <summary>
    /// 父类
    /// </summary>
    class FatherClass { }

    /// <summary>
    /// 子类
    /// </summary>
    class SonClass : FatherClass { }

    class Program
    {
        static void Main(string[] args)
        {
            //隐式转换
            FatherClass sonClass = new SonClass();

            //wait
            Console.ReadKey();
        }
    }
}

向下(Downcasting)转换

向下(Downcasting)转换是父类转为子类

这是显式(Explicitly downcast)转换的

注意:如果转换向下转换失败,运行时将会抛出(InvalidCastException )

实例:

using System;
namespace ConsoleApp1
{
    /// <summary>
    /// 父类
    /// </summary>
    class FatherClass { }

    /// <summary>
    /// 子类
    /// </summary>
    class SonClass : FatherClass { }

    class Program
    {
        static void Main(string[] args)
        {
            //隐式转换(子类转为父类)
            FatherClass sonClass = new SonClass();
            //显式转换(父类转为子类)
            SonClass sonClass2 = (SonClass)sonClass;

            //wait
            Console.ReadKey();
        }
    }
}

可以使用as运算符(as operator)和is运算符(is operator)避免运行时抛出异常

实例:

using System;
namespace ConsoleApp1
{
    /// <summary>
    /// 父类
    /// </summary>
    class FatherClass { }

    /// <summary>
    /// 子类
    /// </summary>
    class SonClass : FatherClass { }

    class Program
    {
        static void Main(string[] args)
        {
            //隐式转换(子类转为父类)
            FatherClass sonClass = new SonClass();
            //显式转换(父类转为子类)
            SonClass result = sonClass as SonClass;
            if (result != null)
            {
                Console.WriteLine(result);
            }

            //wait
            Console.ReadKey();
        }
    }
}

从C# 7开始可以直接在is运算符中定义变量

实例:

using System;
namespace ConsoleApp1
{
    /// <summary>
    /// 父类
    /// </summary>
    class FatherClass { }

    /// <summary>
    /// 子类
    /// </summary>
    class SonClass : FatherClass { }

    class Program
    {
        static void Main(string[] args)
        {
            //隐式转换(子类转为父类)
            FatherClass sonClass = new SonClass();
            //显式转换(父类转为子类)
            if (sonClass is SonClass result)
            {
                Console.WriteLine(result);
            }

            //wait
            Console.ReadKey();
        }
    }
}

数值类型四舍五入问题

如果小数部分小于0.5,则始终向下取整

如果小数部分大于0.5,则始终向上取整

如果小数部分是0.5,非小数部分是奇数,则向上舍入;如果非小数部分是偶数,则向下舍入

Console.WriteLine(Math.Round(10.6));//11
Console.WriteLine(Math.Round(10.4));//10
Console.WriteLine(Math.Round(10.5));//10
Console.WriteLine(Math.Round(10.5, MidpointRounding.ToPositiveInfinity)); //11

ToString()与Parse()/TryParse()方法

ToString()方法将类型转为字符串类型

Parse()/TryParse()静态方法将字符串类型转为具体的类型

注意:Parse()静态方法如果转换失败,会抛出FormatException异常

注意:ToString/Parse/TryParse方法默认基于本地文化进行转换,可以设置文化类型

实例:

string s = true.ToString(); // s = "True"
bool b = bool.Parse(s); // b = true

实例:
```c#
bool failure = int.TryParse("qwerty", out int i1);
bool success = int.TryParse("123", out int i2);

实例:

bool success = int.TryParse ("123", out int _);

实例:

double x = double.Parse ("1.234", CultureInfo.InvariantCulture);

实例:

double x = double.Parse ("1.234", CultureInfo.InvariantCulture);

实例:

string x = 1.234.ToString (CultureInfo.InvariantCulture);

Convert静态类型

说明

Convert静态类型的作用:
Real-to-integral conversions that round rather than truncate

​ Parsing numbers in base 2, 8, and 16

Dynamic conversions

Base-64 translations

使用Convert静态类型强化转换

注意:转换不成功将抛出System.FormatException异常

注意:Convert还可以用于日期转换

实例:

try
{
    bool panda1 = Convert.ToBoolean("true");
    int panda2 = Convert.ToInt32("666");
    decimal panda3 = Convert.ToDecimal("3.14156");
    Console.WriteLine(panda1); //true
    Console.WriteLine(panda2); //666
    Console.WriteLine(panda3); //3.14156
}
catch(FormatException e)
{
    Console.WriteLine(e.Message);
}

进制转换

实例:转为十六进制

int thirty = Convert.ToInt32 ("1E", 16); // Parse in hexadecimal

实例:转为二进制

uint five = Convert.ToUInt32 ("101", 2); // Parse in binary

byte[]与Base64转换(Base-64 conversions)

转为Base64编码字符串

string ToBase64String(byte[] inArray);
string ToBase64String(byte[] inArray, int offset, int length);

使用将Base64编码字符串转为原始值

byte[] FromBase64CharArray(char[] inArray, int offset, int length);
byte[] FromBase64String(string s);

实例:

//原始数据
byte[] someDate = new byte[]
{
    1,2,3,4,5,6
};

//转换Base64编码字符串
string base64String = Convert.ToBase64String(someDate);

//转为原始数据
byte[] originData = Convert.FromBase64String(base64String);

foreach (var item in originData)
{
    Console.WriteLine(item);
}

IFormattable接口

接口的定义

public interface IFormattable
{
   string ToString (string format, IFormatProvider formatProvider);
}

说明:

​ 所有的数值类型都实现了IFormatable接口

​ .NET Core中预定义了NumberFormatInfo、DateTimeFormatInfo、CultureInfo

​ ToString方法的第一个参数是字符串格式(format string)

​ ToString方法的第二个参数是格式提供器(format provider)

实例:使用预定义的数值格式化提供器设置货币的符号

NumberFormatInfo f = new NumberFormatInfo();
f.CurrencySymbol = "$$";
Console.WriteLine (3.ToString ("C", f)); // $$ 3.00

实例:使用预定义的数值格式化提供器设置分隔符

NumberFormatInfo f = new NumberFormatInfo ();
f.NumberGroupSeparator = " ";
Console.WriteLine (12345.6789.ToString ("N3", f)); // 12 345.679

实例:设置文化类型

CultureInfo uk = CultureInfo.GetCultureInfo ("en-GB");
Console.WriteLine (3.ToString ("C", uk)); // £3.00

实例:设置文化无关(based on American culture)

DateTime dt = new DateTime (2000, 1, 2);
CultureInfo iv = CultureInfo.InvariantCulture;
Console.WriteLine (dt.ToString (iv)); // 01/02/2000 00:00:00
Console.WriteLine (dt.ToString ("d", iv)); // 01/02/2000

预定义标准数字格式字符串(standard numeric format strings)

image

image

自定义标准数值格式字符串(Custom numeric format strings)

image

image

image

预定义日期格式化字符串(Date/Time Format Strings)

image

image

实例:

DateTime datetime = DateTime.Now; 
Console.WriteLine(datetime.ToString("d")); //2021/2/17
Console.WriteLine(datetime.ToString("t")); //11:06
Console.WriteLine(datetime.ToLongDateString()); //2021年2月17日
Console.WriteLine(datetime.ToLongTimeString()); //11:06:06
Console.WriteLine(datetime.ToShortDateString()); //2021/2/17
Console.WriteLine(datetime.ToShortTimeString()); //11:06

不分区域的日期字符串格式字符串(Culture-insensitive date/time format strings)

image

XmlConvert用于格式化和解析XML

所在命名空间

using System.Xml;

BitConverter

BitConverter用于二进制转换

实例:

foreach (byte b in BitConverter.GetBytes(3.5))
{
    Console.Write(b + " "); // 0 0 0 0 0 0 12 64
}

动态类型转换(Dynamic conversions)

适合于在运行时才知道类型的场景

使用Convert静态类型的ChangeType静态方法

实例:动态类型转换

Type targetType = typeof (int);
object source = "42";
object result = Convert.ChangeType (source, targetType);
Console.WriteLine (result); // 42
Console.WriteLine (result.GetType()); // System.Int32
posted @ 2022-09-11 08:31  重庆熊猫  阅读(1659)  评论(0编辑  收藏  举报