当前位置:  开发笔记 > 编程语言 > 正文

测试字符串是否为guid而不抛出异常?

如何解决《测试字符串是否为guid而不抛出异常?》经验,为你挑选了8个好方法。

我想尝试将字符串转换为Guid,但我不想依赖捕获异常(

出于性能原因 - 例外是昂贵的

出于可用性原因 - 弹出调试器

出于设计原因 - 预期并非例外

换句话说代码:

public static Boolean TryStrToGuid(String s, out Guid value)
{
    try
    {
        value = new Guid(s);
        return true;
    }
    catch (FormatException)
    {
        value = Guid.Empty;
        return false;
    }
}

不适合.

我会尝试使用RegEx,但由于guid可以括号括起来,括号包裹,没有包装,使其变得困难.

另外,我认为某些Guid值无效(?)


更新1

ChristianK有一个好主意只能抓住FormatException,而不是全部.更改了问题的代码示例以包含建议.


更新2

为什么要担心引发异常?我真的经常期待无效的GUID吗?

答案是肯定的.这就是为什么我使用TryStrToGuid -我期待坏数据.

示例1 可以通过将GUID附加到文件夹名称来指定名称空间扩展.我可能正在解析文件夹名称,检查最终后是否有文本.是一个GUID.

c:\Program Files
c:\Program Files.old
c:\Users
c:\Users.old
c:\UserManager.{CE7F5AA5-6832-43FE-BAE1-80D14CD8F666}
c:\Windows
c:\Windows.old

示例2我可能正在运行一个使用频繁的Web服务器,想要检查一些发布的数据的有效性.我不希望无效数据占用比需要高2-3个数量级的资源.

示例3我可能正在解析用户输入的搜索表达式.

在此输入图像描述

如果他们输入GUID,我想特别处理它们(例如专门搜索该对象,或在响应文本中突出显示并格式化该特定搜索词.)


更新3 - 性能基准

测试转换10,000个好Guids和10,000个坏Guids.

Catch FormatException:
   10,000 good:     63,668 ticks
   10,000 bad:   6,435,609 ticks

Regex Pre-Screen with try-catch:
   10,000 good:    637,633 ticks
   10,000 bad:     717,894 ticks

COM Interop CLSIDFromString
   10,000 good:    126,120 ticks
   10,000 bad:      23,134 ticks

ps我不应该为一个问题辩护.



1> Ian Boyd..:

绩效基准

Catch exception:
   10,000 good:    63,668 ticks
   10,000 bad:  6,435,609 ticks

Regex Pre-Screen:
   10,000 good:   637,633 ticks
   10,000 bad:    717,894 ticks

COM Interop CLSIDFromString
   10,000 good:   126,120 ticks
   10,000 bad:     23,134 ticks

COM Intertop(最快)答案:

/// 
/// Attempts to convert a string to a guid.
/// 
/// The string to try to convert
/// Upon return will contain the Guid
/// Returns true if successful, otherwise false
public static Boolean TryStrToGuid(String s, out Guid value)
{
   //ClsidFromString returns the empty guid for null strings   
   if ((s == null) || (s == ""))   
   {      
      value = Guid.Empty;      
      return false;   
   }

   int hresult = PInvoke.ObjBase.CLSIDFromString(s, out value);
   if (hresult >= 0)
   {
      return true;
   }
   else
   {
      value = Guid.Empty;
      return false;
   }
}


namespace PInvoke
{
    class ObjBase
    {
        /// 
        /// This function converts a string generated by the StringFromCLSID function back into the original class identifier.
        /// 
        /// String that represents the class identifier
        /// On return will contain the class identifier
        /// 
        /// Positive or zero if class identifier was obtained successfully
        /// Negative if the call failed
        /// 
        [DllImport("ole32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = true)]
        public static extern int CLSIDFromString(string sz, out Guid clsid);
    }
}

结论:如果您需要检查字符串是否为guid,并且您关心性能,请使用COM Interop.

如果需要将String表示中的guid转换为Guid,请使用

new Guid(someString);


Upvoting取消我见过的最愚蠢的downvote.
你打开或关闭了调试器吗?异常抛出的性能提高了几倍而无需附加调试器.

2> No Refunds N..:

一旦.net 4.0可用,您就可以使用Guid.TryParse().


一种更快的方法是使用Guid.TryParseExact()方法.
如果解析Guid字符串是应用程序中最慢的部分,那么您很幸运.

3> AnthonyWJone..:

你不会喜欢这个,但是什么让你觉得捕捉异常会变慢?

与成功的算法相比,您期望解析GUID的失败尝试次数是多少?

我的建议是使用您刚刚创建的功能并分析您的代码.如果你发现这个函数确实是一个热点,那么就修复它,但不是之前.


依靠不例外的异常是一种糟糕的形式.这是一个坏习惯,我不希望任何人进入.而且我特别不希望在图书馆例程中这样做,人们会相信它运作良好.
响应我自己的评论=> Guid.TryParse已被添加到框架4.0 --- http://msdn.microsoft.com/en-us/library/system.guid_methods%28VS.100%29.aspx --- thxs MS对这种快速反应;)
EXCEPTIONNAL案例的含义应使用异常:不由开发人员管理.我是微软管理错误的"异常"方式的反对者.防御性编程规则.请微软框架开发人员,考虑在Guid类中添加"TryParse".
好的答案,过早的优化是万恶之源.

4> 小智..:

在.NET 4.0中,您可以编写如下:

public static bool IsValidGuid(string str)
{
    Guid guid;
    return Guid.TryParse(str, out guid);
}


这应该是最好的答案之一.

5> Christian.K..:

我至少会把它重写为:

try
{
  value = new Guid(s);
  return true;
}
catch (FormatException)
{
  value = Guid.Empty;
  return false;
}

你不想在SEHException,ThreadAbortException或其他致命或非相关的东西上说"无效的GUID".

更新:从.NET 4.0开始,Guid有一组新的方法:

Guid.TryParse

Guid.TryParseExact

真的,应该使用那些(如果仅仅是因为它们不是在内部使用try-catch"天真地"实现的).



6> Mark Bracket..:

Interop比捕获异常慢得多:

在快乐的道路上,拥有10,000个Guids:

Exception:    26ms
Interop:   1,201ms

在不愉快的道路上:

Exception: 1,150ms
  Interop: 1,201ms

它更加一致,但也一直较慢.在我看来,配置调试器只会打破未处理的异常会更好.



7> pdavis..:

好吧,这是你需要的正则表达式......

^[A-Fa-f0-9]{32}$|^({|\\()?[A-Fa-f0-9]{8}-([A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}(}|\\))?$|^({)?[0xA-Fa-f0-9]{3,10}(, {0,1}[0xA-Fa-f0-9]{3,6}){2}, {0,1}({)([0xA-Fa-f0-9]{3,4}, {0,1}){7}[0xA-Fa-f0-9]{3,4}(}})$

但这仅适用于初学者.您还必须验证日期/时间等各个部分是否在可接受的范围内.我无法想象这比你已经概述的try/catch方法更快.希望您没有收到那么多无效的GUID来保证这种类型的支票!



8> JMD..:

出于可用性原因 - 弹出调试器

如果您要使用try/catch方法,可以添加[System.Diagnostics.DebuggerHidden]属性,以确保调试器不会中断,即使您已将其设置为中断.

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有