Skip to content

Commit 5719fbb

Browse files
committed
[imporv]优化字符串转为数字时的内存分配,提升性能
1 parent 3b6ddc5 commit 5719fbb

File tree

1 file changed

+57
-24
lines changed

1 file changed

+57
-24
lines changed

NewLife.Core/Common/Utility.cs

+57-24
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,15 @@ public virtual Int32 ToInt(Object? value, Int32 defaultValue)
202202
if (value is String str)
203203
{
204204
// 拷贝而来的逗号分隔整数
205-
str = str.Replace(",", null);
206-
str = ToDBC(str).Trim();
207-
return str.IsNullOrEmpty() ? defaultValue : Int32.TryParse(str, out var n) ? n : defaultValue;
205+
Span<Char> tmp = stackalloc Char[str.Length];
206+
var rs = TrimNumber(str.AsSpan(), tmp);
207+
if (rs == 0) return defaultValue;
208+
209+
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
210+
return Int32.TryParse(tmp[..rs], out var n) ? n : defaultValue;
211+
#else
212+
return Int32.TryParse(new String(tmp[..rs].ToArray()), out var n) ? n : defaultValue;
213+
#endif
208214
}
209215

210216
// 特殊处理时间,转Unix秒
@@ -278,9 +284,15 @@ public virtual Int64 ToLong(Object? value, Int64 defaultValue)
278284
if (value is String str)
279285
{
280286
// 拷贝而来的逗号分隔整数
281-
str = str.Replace(",", null);
282-
str = ToDBC(str).Trim();
283-
return str.IsNullOrEmpty() ? defaultValue : Int64.TryParse(str, out var n) ? n : defaultValue;
287+
Span<Char> tmp = stackalloc Char[str.Length];
288+
var rs = TrimNumber(str.AsSpan(), tmp);
289+
if (rs == 0) return defaultValue;
290+
291+
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
292+
return Int64.TryParse(tmp[..rs], out var n) ? n : defaultValue;
293+
#else
294+
return Int64.TryParse(new String(tmp[..rs].ToArray()), out var n) ? n : defaultValue;
295+
#endif
284296
}
285297

286298
// 特殊处理时间,转Unix毫秒
@@ -349,8 +361,15 @@ public virtual Double ToDouble(Object? value, Double defaultValue)
349361
// 特殊处理字符串,也是最常见的
350362
if (value is String str)
351363
{
352-
str = ToDBC(str).Trim();
353-
return str.IsNullOrEmpty() ? defaultValue : Double.TryParse(str, out var n) ? n : defaultValue;
364+
Span<Char> tmp = stackalloc Char[str.Length];
365+
var rs = TrimNumber(str.AsSpan(), tmp);
366+
if (rs == 0) return defaultValue;
367+
368+
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
369+
return Double.TryParse(tmp[..rs], out var n) ? n : defaultValue;
370+
#else
371+
return Double.TryParse(new String(tmp[..rs].ToArray()), out var n) ? n : defaultValue;
372+
#endif
354373
}
355374

356375
if (value is Byte[] buf && buf.Length <= 8)
@@ -383,8 +402,15 @@ public virtual Decimal ToDecimal(Object? value, Decimal defaultValue)
383402
// 特殊处理字符串,也是最常见的
384403
if (value is String str)
385404
{
386-
str = ToDBC(str).Trim();
387-
return str.IsNullOrEmpty() ? defaultValue : Decimal.TryParse(str, out var n) ? n : defaultValue;
405+
Span<Char> tmp = stackalloc Char[str.Length];
406+
var rs = TrimNumber(str.AsSpan(), tmp);
407+
if (rs == 0) return defaultValue;
408+
409+
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
410+
return Decimal.TryParse(tmp[..rs], out var n) ? n : defaultValue;
411+
#else
412+
return Decimal.TryParse(new String(tmp[..rs].ToArray()), out var n) ? n : defaultValue;
413+
#endif
388414
}
389415

390416
if (value is Byte[] buf)
@@ -450,7 +476,6 @@ public virtual Boolean ToBoolean(Object? value, Boolean defaultValue)
450476
// 特殊处理字符串,也是最常见的
451477
if (value is String str)
452478
{
453-
//str = ToDBC(str).Trim();
454479
str = str.Trim();
455480
if (str.IsNullOrEmpty()) return defaultValue;
456481

@@ -459,8 +484,6 @@ public virtual Boolean ToBoolean(Object? value, Boolean defaultValue)
459484
if (String.Equals(str, Boolean.TrueString, StringComparison.OrdinalIgnoreCase)) return true;
460485
if (String.Equals(str, Boolean.FalseString, StringComparison.OrdinalIgnoreCase)) return false;
461486

462-
// 特殊处理用数字0和1表示布尔型
463-
str = ToDBC(str);
464487
return Int32.TryParse(str, out var n) ? n > 0 : defaultValue;
465488
}
466489

@@ -604,22 +627,32 @@ public virtual DateTimeOffset ToDateTimeOffset(Object? value, DateTimeOffset def
604627
}
605628
}
606629

607-
/// <summary>全角为半角</summary>
608-
/// <remarks>全角半角的关系是相差0xFEE0</remarks>
609-
/// <param name="str"></param>
630+
/// <summary>清理整数字符串,去掉常见分隔符,替换全角数字为半角数字</summary>
631+
/// <param name="input"></param>
632+
/// <param name="output"></param>
610633
/// <returns></returns>
611-
private static String ToDBC(String str)
634+
private static Int32 TrimNumber(ReadOnlySpan<Char> input, Span<Char> output)
612635
{
613-
var ch = str.ToCharArray();
614-
for (var i = 0; i < ch.Length; i++)
636+
var rs = 0;
637+
for (var i = 0; i < input.Length; i++)
615638
{
639+
// 去掉逗号分隔符
640+
var ch = input[i];
641+
if (ch == ',' || ch == '_' || ch == ' ') continue;
642+
616643
// 全角空格
617-
if (ch[i] == 0x3000)
618-
ch[i] = (Char)0x20;
619-
else if (ch[i] is > (Char)0xFF00 and < (Char)0xFF5F)
620-
ch[i] = (Char)(ch[i] - 0xFEE0);
644+
if (ch == 0x3000)
645+
ch = (Char)0x20;
646+
else if (ch is > (Char)0xFF00 and < (Char)0xFF5F)
647+
ch = (Char)(input[i] - 0xFEE0);
648+
649+
// 数字和小数点 以外字符,认为非数字
650+
if (ch is not '.' and (< '0' or > '9')) return 0;
651+
652+
output[rs++] = ch;
621653
}
622-
return new String(ch);
654+
655+
return rs;
623656
}
624657

625658
/// <summary>去掉时间日期秒后面部分,可指定毫秒ms、秒s、分m、小时h</summary>

0 commit comments

Comments
 (0)