c#测试字符串是否为GUID的几种方法

以前为了赶项目遇到这种需求时,也没过多考虑性能因素,随便写了一个(现在看起来很原始的)方法来实现:

static bool IsGuidByError(string strSrc)
        {
            if (String.IsNullOrEmpty(strSrc)) { return false; }
            bool _result = false;
            try
            {
                Guid _t = new Guid(strSrc);
                _result = true;
            }
            catch { }
            return _result;

        }

但是大家都知道,异常捕获是要有性能损耗的。今天想了想:其实还有其它方法,也许会更好

static bool IsGuidByReg(string strSrc)
        {
            Regex reg = new Regex("^[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.Compiled);
            return reg.IsMatch(strSrc);
        }

此外,根据Guid的格式规则:总长数36位,由4个'-'分隔,每一段都是由数字+英文字母组合而成。也可以自己写一个算法:

static bool IsGuidByArr(string strSrc)
        {
            if (String.IsNullOrEmpty(strSrc) || strSrc.Length!=36) { return false; }
            string[] arr = strSrc.Split('-');
            if (arr.Length != 5) { return false; }
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr[i].Length; j++)
                {
                    char a = arr[i][j];
                    if (!((a >= 48 && a <= 57) || (a >= 65 && a <= 90) || (a >= 97 && a <= 122)))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

另:经猎风同学提醒,应该还要考虑到正则表达式不编译的情况,所以再加上这一段

static bool IsGuidByRegNoComplied(string strSrc)
        {
            Regex reg = new Regex("^[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}$");
            return reg.IsMatch(strSrc);
        }

此外:尘尘同学在回复中提醒到还有Guid的TryParse/Parse方法(不过该方法是.Net 4.0才新增加的)

static bool IsGuidByParse(string strSrc) 
        {
            Guid g = Guid.Empty;
            return Guid.TryParse(strSrc, out g);
        }

对于猎风与尘尘的反馈表示感谢!ok,搞了这么多方法,是骡子是马,溜溜便知:

先测试字符串格式正常的情况

using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {


        static void Main(string[] args)
        {

            string a = "C0869370-70BF-4408-A8CF-72A77BB1D788";           
            Console.WriteLine(IsGuidByError(a));
            Console.WriteLine(IsGuidByReg(a));
            Console.WriteLine(IsGuidByRegNoComplied(a));
            Console.WriteLine(IsGuidByArr(a));
            Console.WriteLine(IsGuidByParse(a));
            Console.WriteLine("测试开始------------------->\n");



            Stopwatch sw = new Stopwatch();

            int count = 5000;
            int times = 5;
            long result = 0;

            for (int i = 0; i < times; i++)
            {
                result += Test(sw, count, a, MethodType.异常);
            }


            Console.WriteLine("\n{0}次×{1}轮测试,[异常]方法平均每轮速度:{2}\n", count, times, result / times);

            Console.Write("\n");


            result = 0;

            for (int i = 0; i < times; i++)
            {
                result += Test(sw, count, a, MethodType.正则);
            }

            Console.WriteLine("\n{0}次×{1}轮测试,[正则]方法平均每轮速度:{2}\n", count, times, result / times);

            Console.Write("\n");

            result = 0;

            for (int i = 0; i < times; i++)
            {
                result += Test(sw, count, a, MethodType.正则不编译);
            }

            Console.WriteLine("\n{0}次×{1}轮测试,[正则不编译]方法平均每轮速度:{2}\n", count, times, result / times);

            Console.Write("\n");

            result = 0;
            for (int i = 0; i < times; i++)
            {
                result += Test(sw, count, a, MethodType.数组);
            }

            Console.WriteLine("\n{0}次×{1}轮测试,[数组]方法平均每轮速度:{2}\n", count, times, result / times);

            result = 0;
            for (int i = 0; i < times; i++)
            {
                result += Test(sw, count, a, MethodType.TryParse);
            }

            Console.WriteLine("\n{0}次×{1}轮测试,[TryParse]方法平均每轮速度:{2}\n", count, times, result / times);


            Console.Read();
        }


        static bool IsGuidByArr(string strSrc)
        {
            if (String.IsNullOrEmpty(strSrc) || strSrc.Length!=36) { return false; }
            string[] arr = strSrc.Split('-');
            if (arr.Length != 5) { return false; }
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr[i].Length; j++)
                {
                    char a = arr[i][j];
                    if (!((a >= 48 && a <= 57) || (a >= 65 && a <= 90) || (a >= 97 && a <= 122)))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        static bool IsGuidByError(string strSrc)
        {
            if (String.IsNullOrEmpty(strSrc)) { return false; }
            bool _result = false;
            try
            {
                Guid _t = new Guid(strSrc);
                _result = true;
            }
            catch { }
            return _result;

        }

        static bool IsGuidByReg(string strSrc)
        {
            Regex reg = new Regex("^[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.Compiled);
            return reg.IsMatch(strSrc);
        }


        static bool IsGuidByRegNoComplied(string strSrc)
        {
            Regex reg = new Regex("^[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}$");
            return reg.IsMatch(strSrc);
        }


        static bool IsGuidByParse(string strSrc) 
        {
            Guid g = Guid.Empty;
            return Guid.TryParse(strSrc, out g);
        }

        /// <summary>
        /// 测试
        /// </summary>
        /// <param name="sw"></param>
        /// <param name="count"></param>
        /// <param name="a"></param>
        /// <param name="useRegularExpressions"></param>
        /// <returns></returns>
        static long Test(Stopwatch sw, int count, string a, MethodType type)
        {
            bool _test = false;
            int i = 0;
            sw.Reset();
            sw.Start();
            for (i = 0; i < count; i++)
            {
                switch (type)
                {
                    case MethodType.异常:
                        _test = IsGuidByError(a);
                        break;
                    case MethodType.数组:
                        _test = IsGuidByArr(a);
                        break;
                    case MethodType.正则:
                        _test = IsGuidByReg(a);
                        break;
                    case MethodType.正则不编译:
                        _test = IsGuidByReg(a);
                        break;
                    case MethodType.TryParse:
                        _test = IsGuidByParse(a);
                        break;
                    default:
                        break;
                }
            }
            sw.Stop();
            Console.Write(sw.ElapsedMilliseconds + "\n");
            return sw.ElapsedMilliseconds;
        }

        enum MethodType
        {
            异常,
            数组,
            正则,
            正则不编译,
            TryParse
        }
    }
}

True True True True True 测试开始------------------->

5 5 5 5 5

5000次×5轮测试,[异常]方法平均每轮速度:5

9219 9235 9360 9272 9103

5000次×5轮测试,[正则]方法平均每轮速度:9237

9095 9113 9116 9181 9156

5000次×5轮测试,[正则不编译]方法平均每轮速度:9132

9 5 7 5 6

5000次×5轮测试,[数组]方法平均每轮速度:6

4 4 4 4 4

5000次×5轮测试,[TryParse]方法平均每轮速度:4

可以看到,在字符串格式正确的情况下,异常未被触发,除正则表达式显得巨慢以外,其它三种方法相差无已。

再来看下字符串格式错误的情况下

把string a = "C0869370-70BF-4408-A8CF-72A77BB1D788";改成string a = "C0869370-70BF-4408-A8CF-72A77BB1D788111111111111";

输出结果如下:

False False False False False 测试开始------------------->

35575 33681 33752 33985 33804

5000次×5轮测试,[异常]方法平均每轮速度:34159

8982 9104 9087 8959 8973

5000次×5轮测试,[正则]方法平均每轮速度:9021

9041 9102 9056 8977 8872

5000次×5轮测试,[正则不编译]方法平均每轮速度:9009

0 0 0 0 0

5000次×5轮测试,[数组]方法平均每轮速度:0

1 1 1 1 1

5000次×5轮测试,[TryParse]方法平均每轮速度:1

很明显,这时候异常带来的性能开销就很可观了,反而基于“字符数组”的检测方法最快(这跟测试用例有关,因为该字符串长度大于36,直接就出局了,连后面的循环都不用,如果换成其它错误的格式比如:“C0869370-70BF-4408-A8CF-72A77BB1D78?”,可能略有差异)

结论:综合考虑,推荐大家用“基于字符数组”的检测方法或Guid内置的TryParse方法,异常捕获和正则表达式方法应该避免使用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客猴

Django 学习笔记之模型高级用法(下)

除了抽象模型,在模型中定义的字段都会成为表中的列。如果我们需要给模型指定其他一些信息,例如排序方式、数据库表名等,就需要用到 Meta。Meta 是一个可选的类...

10120
来自专栏数据科学学习手札

(数据科学学习手札06)Python在数据框操作上的总结(初级篇)

数据框(Dataframe)作为一种十分标准的数据结构,是数据分析中最常用的数据结构,在Python和R中各有对数据框的不同定义和操作。 Python 本文涉及...

72350
来自专栏聊聊技术

原 "二分查找(Binary Search

445110
来自专栏数据结构与算法

HDU4352 XHXJ's LIS(LIS 状压)

刚开始的思路是$f[i][j]$表示到第$i$位,LIS长度为$j$的方案。 然而发现根本不能转移,除非知道了之前的状态然后重新dp一遍。。

10630
来自专栏木头编程 - moTzxx

PHP算法 [杨辉三角的求解]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

17520
来自专栏数据结构与算法

11:大整数减法

11:大整数减法 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB描述 求两个大的正整数相减的差。 输入共2行,第1行是被减...

297100
来自专栏蜉蝣禅修之道

Max-Min Fairness带宽分配算法

26760
来自专栏java 成神之路

java.util.Random 实现原理

36650
来自专栏软件测试经验与教训

Python学习笔记(15)-文件替换

39290
来自专栏用户2442861的专栏

阿里巴巴2014秋季校园招聘-软件研发工程师笔试题详解

http://blog.csdn.net/zs634134578/article/details/21018845

16220

扫码关注云+社区

领取腾讯云代金券