C#类型转换

前面介绍了整数、浮点数、字符和字符串的处理,实际开发工作中,不同类型的数据经常会相互转换,本文会讨论如何将其它类型转换为字符串,如何使用Convert类,以及如何使用值类型的Parse()和TryParse()方法进行类型转换,并将常用的转换操作封装到cfx/Str类。

将其它类型转换为字符串

需要将其它类型转换为字符串时,很多时候是可以自动完成的,如Console.WriteLine()方法,以及使用+运算符连接字符串和其它类型的数据等。需要注意布尔(bool)类型,true和false值转换为字符串形式分别是"True"和"False",这也是为什么在Console.WriteLine()方法中显示的true和false值总是True和False的原因。

将其它类型转换为字符串时,也可以调用对象(变量)的ToString()方法,方法会返回数据默认的字符串形式。此外,在自定义类型中也可以重写ToString()方法,并返回所需要的对象信息,如下面的代码。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Human tom = new Human() { Name = "Tom" };
            Console.WriteLine(tom.ToString());
        }
    }
    //
    class Human 
    {
        public string Name { get; set; }
        //
        new public string ToString()
        {
            return "Human对象,Name(" + Name + ")";
        }
    }
}

代码中定义了Human类,并使用new关键字定义了新的ToString()方法,执行代码会显示“Human对象,Name(Tom)”。

Convert类

Convert类定义在System命名空间,定义了一系列的类型转换方法,下面先来看ToInt32()方法的应用。

ToInt32()方法的功能是将各种类型的数据转换为32位有符号整数,即C#中的int类型和.NET Framework中的Int32类型。方法包含了一系列的重构版本,可以使用各种类型的参数,其中,对于字符串数据,还可以指定包含数据的进制(默认为十进制),如下面的代码。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Convert.ToInt32("123")); // 123
            Console.WriteLine(Convert.ToInt32("10",8));  // 8
            Console.WriteLine(Convert.ToInt32("A", 16)); // 10
            Console.WriteLine(Convert.ToInt32("11", 2)); // 3
        }
    }
}

ToInt32()方法会将null值转换为0,false值转换为0,true值转换为1,如下面的代码。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Convert.ToInt32(null)); // 0
            Console.WriteLine(Convert.ToInt32(false));  // 0
            Console.WriteLine(Convert.ToInt32(true)); // 1
        }
    }
}

此外,当参数为浮点数时会对小数部分四舍五入,如122.56会转换为123。当参数内容不能转换为Int32类型(int)时,会抛出异常。

Convert.ToString()方法中,当参数一是整数时,可以使用参数二指定转换为指定进制格式的字符串,默认为十进制。下面的代码演示了相关应用。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Convert.ToString(15)); // 15
            Console.WriteLine(Convert.ToString(15, 2)); // 1111
            Console.WriteLine(Convert.ToString(15, 8));  // 17
            Console.WriteLine(Convert.ToString(15, 16)); // f
        }
    }
}

需要注意的是,Convert.ToString()方法转换null时依然是null,true转换为"True",false转换为"False"。

Convert类中定义的ToXXX系列方法,其中的XXX为.NET Framework中的类型名,各个方法的重构版本中又可以设置各种类型的数据,如各种数值类型、string、bool、DateTime、object类型等,可以根据需要灵活应用。请注意,如果参数不能正确转换为目标类型数据会抛出异常。

值类型的Parse()和TryParse()方法

各种值类型的Parse()方法可以将字符串类型转换为对应的类型,如int.Parse(s)会将字符串s的内容转换为int类型,如果转换失败会抛出异常,需要注意,包含浮点数的字符串也无法转换为整数。下面的代码代码演示了相关应用。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(int.Parse("123"));   // 123
            Console.WriteLine(int.Parse("122.56"));   // 错误
            Console.WriteLine(int.Parse("xyz"));   // 错误
        }
    }
}

TryParse()方法会尝试将参数一的字符串内容转换为对应的类型,并通过参数二输出转换结果,方法会返回bool类型数据,成功转换返回true,否则返回false。下面的代码演示了相关应用。

C#
using System;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            int result;
            if(int.TryParse("123",out result))
            {
                Console.WriteLine(result);
            }
            else
            {
                Console.WriteLine("转换失败");
            }
        }
    }
}

此代码会显示123,可以修改int.TryParse()方法第一个参数的内容来观察执行结果,如果字符串内容不能转换为int类型会显示“转换失败”,这里,浮点数格式的字符串内容同样不能转换为int类型。

各种数值类型、DateTime等类型都定义了Parse()和TryParse()方法,可以根据需要选择应用。

封装Str类

实际工作中,可能还需要各种数据转换逻辑,比如,对于在界面中输入的数据可以尝试转换为指定类型,如果转换失败就使用默认值。下面的代码,在cfx/Str.cs文件中创建Str类,并创建ToInt()静态方法。

C#
using System;
using System.Text.RegularExpressions;

namespace cfx
{
    public static class Str
    {
        // 转换为int类型,默认值为0
        public static int ToInt(this string s, int defVal = 0)
        {
            int result;
            if (int.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
    }
}

代码中,在cfx命名空间里创建了Str静态类,其中定义了ToInt()静态方法,其中,参数一指定需要转换为int类型的字符串内容,参数二指定转换失败后返回的默认值;方法会返回int类型的数据。方法中调用了int类型的TryParse()方法执行转换,转换成功返回转换结果,否则返回默认值。

此外,请注意ToInt()方法的第一个参数使用了this关键字,也就是将ToInt()方法定义为string类型的扩展方法。下面的代码演示了Str.ToInt()方法的应用。

C#
using System;
using cfx;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("123".ToInt());  // 123
            Console.WriteLine(Str.ToInt("123")); // 123
            Console.WriteLine("xyz".ToInt());  // 0
            Console.WriteLine("xyz".ToInt(-1));  // -1
        }
    }
}

cfx.Str类中,为什么将ToInt()方法的第一个参数设置为string类型呢?

应用开发中,如Web项目中,各种字段(Web控件)中获取的数据大多是文本类型,所以,将文本转换为所需的类型就显得格外重要,也最常见。当然,在实际工作中,如果需要更多的转换逻辑,也可以创建相应的转换方法,如果不想创建过多的重构版本,可以通过object类型创建通用操作方法,如下面的代码(cfx/Obj.cs)。

C#
using System;

namespace cfx
{
    public static class Obj
    {
        // 转换为int类型,默认值为0
        public static int ToInt(object obj, int defVal = 0)
        {
            int result;
            if (obj != null && int.TryParse(obj.ToString(), out result))
                return result;
            else
                return defVal;
        }
    }
}

在Obj.ToInt()方法,参数一指定为object类型,这里没有使用this关键字,原因是object是所有类型的终极基类,在object类型上添加扩展方法并不是一个好主意。参数二同样指定默认值。方法中,多了参数一是否为null值的判断条件,如果是null值则返回默认值,如果不是,则判断其字符串格式的数据是否能够转换为int类型,转换成功返回转换数据,否则返回默认值。下面的代码演示了相关应用。

C#
using System;
using cfx;

namespace csfx_demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Obj.ToInt("123")); // 123
            Console.WriteLine(Obj.ToInt("xyz"));  // 0
            Console.WriteLine(Obj.ToInt("xyz", -1));  // -1
        }
    }
}

Str和Obj类中可以根据需要封装一些常用类型的转换方法,下面的代码给出了Str类型的一些代码,可以参考使用。

C#
using System;
using System.Text.RegularExpressions;

namespace cfx
{
    public static class Str
    {
        // 转换为int类型,默认值为0
        public static int ToInt(this string s, int defVal = 0)
        {
            int result;
            if (int.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static uint ToUInt(this string s, uint defVal = 0)
        {
            uint result;
            if (uint.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static long ToLng(this string s, long defVal = 0L)
        {
            long result;
            if (long.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static ulong ToULng(this string s, ulong defVal = 0L)
        {
            ulong result;
            if (ulong.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static float ToSng(this string s, float defVal = 0F)
        {
            float result;
            if (float.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static double ToDbl(this string s, double defVal = 0D)
        {
            double result;
            if (double.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
        //
        public static decimal ToDec(this string s, decimal defVal = 0M)
        {
            decimal result;
            if (decimal.TryParse(s, out result))
                return result;
            else
                return defVal;
        }
    }
}