posts - 185,  comments - 1071,  trackbacks - 43

.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

    }

 

posted on 2007-01-26 12:15 henry 阅读(1545) 评论(5)  编辑 收藏 网摘

FeedBack:
2007-01-26 12:21 | 亚历山大同志      
貌似有tryparse()这样子的方法
  回复  引用  查看    
#2楼[楼主]
2007-01-26 12:34 | henry      
这里的实现是基于接口主要是方便和反射处理整合,方便扩展日期等其他类型转换器.
tryparse()好象是Double提供, Double精高即使不是有效的int16也可以向下转换.如果能接受这样的转换的确是可以用这种方法.

呵呵看来2.0的其他直类型都提供了tryparse()这个方法,看来可以节省不少时间编写值类型的转换.还花了些时间看Castle.Components.Binder:(

  回复  引用  查看    
2007-01-26 13:04 | 亚历山大同志      
1.1下还是很好用,现在互联星空可不敢升级到2.0,升级不如重做一个
  回复  引用  查看    
2007-01-26 13:55 | 红移[未注册用户]
http://msdn2.microsoft.com/en-us/library/system.convert.changetype(VS.80).aspx

可以参考 Convert类

  回复  引用    
2007-01-26 17:50 | vivianfdlpw[未注册用户]
TryParse方法
  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 631066




历史上的今天:
2006-01-26 今年年头很黑仔!

相关文章:

相关链接:
<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

与我联系

搜索

 

常用链接

留言簿

我参加的小组

我的标签

随笔分类

最新评论

60天内阅读排行