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

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

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

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方法,异常捕获和正则表达式方法应该避免使用。

目录
相关文章
|
17天前
|
测试技术 API 项目管理
API测试方法
【10月更文挑战第18天】API测试方法
30 1
|
15天前
|
测试技术 UED
软件测试中的“灰盒”方法:一种平衡透明度与效率的策略
在软件开发的复杂世界中,确保产品质量和用户体验至关重要。本文将探讨一种被称为“灰盒测试”的方法,它结合了白盒和黑盒测试的优点,旨在提高测试效率同时保持一定程度的透明度。我们将通过具体案例分析,展示灰盒测试如何在实际工作中发挥作用,并讨论其对现代软件开发流程的影响。
|
15天前
|
测试技术 C# 数据库
C# 单元测试框架 NUnit 一分钟浅谈
【10月更文挑战第17天】单元测试是软件开发中重要的质量保证手段,NUnit 是一个广泛使用的 .NET 单元测试框架。本文从基础到进阶介绍了 NUnit 的使用方法,包括安装、基本用法、参数化测试、异步测试等,并探讨了常见问题和易错点,旨在帮助开发者有效利用单元测试提高代码质量和开发效率。
117 64
|
26天前
|
运维
【运维基础知识】用dos批处理批量替换文件中的某个字符串(本地单元测试通过,部分功能有待优化,欢迎指正)
该脚本用于将C盘test目录下所有以t开头的txt文件中的字符串“123”批量替换为“abc”。通过创建批处理文件并运行,可实现自动化文本替换,适合初学者学习批处理脚本的基础操作与逻辑控制。
119 56
|
7天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
11 2
|
11天前
|
缓存 监控 数据挖掘
C# 一分钟浅谈:性能测试与压力测试
【10月更文挑战第20天】本文介绍了性能测试和压力测试的基础概念、目的、方法及常见问题与解决策略。性能测试关注系统在正常条件下的响应时间和资源利用率,而压力测试则在超出正常条件的情况下测试系统的极限和潜在瓶颈。文章通过具体的C#代码示例,详细探讨了忽视预热阶段、不合理测试数据和缺乏详细监控等常见问题及其解决方案,并提供了如何避免这些问题的建议。
33 7
|
13天前
|
Kubernetes 测试技术 持续交付
C# 一分钟浅谈:集成测试与系统测试
【10月更文挑战第19天】本文详细介绍了集成测试和系统测试的概念、目的及其在软件开发中的重要性。通过分析常见问题和易错点,结合代码示例,探讨了如何通过代码规范、自动化测试和持续集成等方法提高测试效果,确保软件质量和可靠性。
33 1
|
14天前
|
测试技术 C# 数据库
C# 一分钟浅谈:测试驱动开发 (TDD) 实践
【10月更文挑战第18天】测试驱动开发(TDD)是一种软件开发方法论,强调先编写测试代码再编写功能代码,以确保代码质量和可维护性。本文从 TDD 的基本概念入手,详细介绍了其核心步骤——编写测试、运行测试并失败、编写代码使测试通过,以及“红绿重构”循环。文章还探讨了 TDD 的优势,包括提高代码质量、促进设计思考、减少调试时间和文档化。此外,文中分析了常见问题及解决方案,如测试覆盖率不足、测试代码过于复杂、忽视重构和测试依赖过多,并通过一个简单的计算器类的代码案例,展示了 TDD 的实际应用过程。
31 1
|
27天前
|
测试技术 Python
自动化测试项目学习笔记(三):Unittest加载测试用例的四种方法
本文介绍了使用Python的unittest框架来加载测试用例的四种方法,包括通过测试用例类、模块、路径和逐条加载测试用例。
55 0
自动化测试项目学习笔记(三):Unittest加载测试用例的四种方法
|
27天前
|
测试技术 Python
自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法
本文主要介绍了自动化测试中setup、teardown、断言方法的使用,以及unittest框架中setUp、tearDown、setUpClass和tearDownClass的区别和应用。
49 0
自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法