什么时候应该实现String到值类型的转换器
2007-01-26 12:15
260 查看
.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
}
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
}
相关文章推荐
- 一开始实现的时候,不知道贝塞尔曲线,自己去思考其他方法实现了。怎么想到用到贝塞尔曲线?以后碰到类似问题,应该先在网上找找都有什么方法实现。
- 什么时候应该使用Web Service
- PHP教程:我们什么时候应该使用异常?
- ViewController 的loadView、viewDidLoad、viewDidUnload分别是什么时候调用的,在自定义ViewCointroller时在这几个函数中应该做什么工作?
- 什么时候应该使用SQL Server锁模式
- 什么时候应该使用Web Service -
- Mybatis中什么时候应该声明jdbcType
- 什么时候应该使用 ==?什么时候应该使用 Equals?
- 什么时候应该使用索引,应该使用什么类型的索引
- 你知道什么时候应该使用Web Service吗?
- 使用SVN时候我们应该注意些什么?
- 什么时候使用指针?什么时候使用引用?什么时候应该按值传递?
- 什么时候应该用equals(),什么时候应该用==
- 26岁的时候 你应该考虑些什么
- Redis持久化RDB和AOF优缺点是什么,怎么实现的?我应该用哪一个?
- 什么时候应该使用$scope.$apply()
- 什么时候应该使用 ==?什么时候应该使用 Equals?
- PHP教程:我们什么时候应该使用异常?
- 什么时候应该使用Web Service
- 014敲代码将一个栈按升序排序,对这个栈是怎样实现的,你不应该做不论什么特殊的如果(keep it up)