现在的位置: 首页 > 综合 > 正文

什么时候应该实现String到值类型的转换器

2012年05月01日 ⁄ 综合 ⁄ 共 4552字 ⁄ 字号 评论关闭

.Net内部的值类型都提供Parse用来处理string的转换,相信在托管代码下这样转换应该是最高效的了;看上去自己实现一个string的转换对象似乎没有这个必要。但Parse方法有个缺点,除非能保证提供的string有效性要不就会发异常。有时为了保证转换错误不会影响程序会这样做:

try

{

    value = Int16.Parse(str[i]);

}

catch

{}

以上代码看去并没有什么问题,但在某些场景下就是问题的根源!

有时候实现一个对象数据绑定器,数据来源于Web的提交信息。通过绑定功能可以节省大量手写代码:

Codes.OrderSearch search = BindObject<Codes.OrderSearch>("");

由于Web提供的信息都是基于String,因为通过反射根据类型进行转换;为了保证个别成员的转换错误不影响整个过程那只有加上try{}catch{}。因为组件内部是不能保证提供的String合法性,因此在转换过程抛出异常是经常的事;就是因为异常的抛出会导致BindObject的过程中性能会出现严重问题。

       为了证实以上问题写了一个小小的测试用例:

static void Test1()

{

    string[] str = new string[] {"2123","234s12","12123","4325","12er243","-4112" ,"3rer32","-1213","121","22342313"};

    Int16 value = -1;

    object converobj;

    IStringConverter toint = new ToInt16();

   

    bool ok;

    Stopwatch watch = new System.Diagnostics.Stopwatch();

    for (int i = 0; i < 10; i++)

    {

        watch.Reset();

        watch.Start();

        try

        {

            value = Int16.Parse(str[i]);

        }

        catch

        {

            value = -1;

        }

        watch.Stop();

        Console.WriteLine("value:{0}", value!=-1?(object)value:"Error");

        Console.WriteLine("System Pares Time:{0}", watch.Elapsed);

 

        watch.Reset();

        watch.Start();

        converobj = toint.ConvertTo(str[i], out ok);

        if (ok)

            value = (Int16)converobj;

        else

            value = -1;

        watch.Stop();

        Console.WriteLine("value:{0}", value !=-1 ? (object)value : "Error");

        Console.WriteLine("Custom Pares Time:{0}", watch.Elapsed);

        Console.WriteLine("====================================");

        decimal de = decimal.Parse("1212.45");

    }

}

下页结果才能看到问题原因:

value:2123

System Pares Time:00:00:00.0000167

value:2123

Custom Pares Time:00:00:00.0014842

====================================

value:Error

System Pares Time:00:00:00.0046785

value:Error

Custom Pares Time:00:00:00.0000388

====================================

value:12123

System Pares Time:00:00:00.0000148

value:12123

Custom Pares Time:00:00:00.0000785

====================================

value:4325

System Pares Time:00:00:00.0000139

value:4325

Custom Pares Time:00:00:00.0000145

====================================

value:Error

System Pares Time:00:00:00.0050481

value:Error

Custom Pares Time:00:00:00.0000156

====================================

value:-4112

System Pares Time:00:00:00.0000153

value:-4112

Custom Pares Time:00:00:00.0000153

====================================

value:Error

System Pares Time:00:00:00.0037747

value:Error

Custom Pares Time:00:00:00.0000164

====================================

value:-1213

System Pares Time:00:00:00.0000148

value:-1213

Custom Pares Time:00:00:00.0000156

====================================

value:121

System Pares Time:00:00:00.0000142

value:121

Custom Pares Time:00:00:00.0000148

====================================

value:Error

System Pares Time:00:00:00.0034585

value:Error

Custom Pares Time:00:00:00.0000159

====================================

从结果可以看到在转换错误时所负出的代价。

因此在某些场景下使用自定义转换类还是很有必要的。

 

ToInt16的实现代码:

    public class ToInt16 : IStringConverter

    {

 

        #region IStringConverter 成员

 

        object IStringConverter.ConvertTo(string value, out bool succeeded)

        {

            succeeded = (value != null && value != "");

            if (!succeeded)

                return null;

            int count;

            char[] chars = value.ToCharArray();

            count = chars.Length;

            if (count > 6)

            {

                succeeded = false;

                return null;

            }

            if (count == 6 && chars[0] != '-')

            {

                succeeded = false;

                return null;

            }

            for (int i = 0; i < count; i++)

            {

                succeeded = char.IsNumber(chars[i]) || (chars[i] == '-' && i == 0);

                if (!succeeded)

                    return null;

            }

            if (chars[0] == '-')

            {

                if (count == 6)

                {

                    succeeded = char.GetNumericValue(chars[1]) <= 3 &&

                                char.GetNumericValue(chars[2]) <= 2 &&

                                char.GetNumericValue(chars[3]) <= 7 &&

                                char.GetNumericValue(chars[4]) <= 6 &&

                                char.GetNumericValue(chars[5]) <= 8;

                }

            }

            else

            {

                if (count == 5)

                {

                    succeeded = char.GetNumericValue(chars[0]) <= 3 &&

                                char.GetNumericValue(chars[1]) <= 2 &&

                                char.GetNumericValue(chars[2]) <= 7 &&

                                char.GetNumericValue(chars[3]) <= 6 &&

                                char.GetNumericValue(chars[4]) <= 7;

                }

            }

            if (succeeded)

                return Int16.Parse(value);

            return null;

           

        }

 

        #endregion

    }

 

抱歉!评论已关闭.