문자열을 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를 추가하여 네임 스페이스 확장명을 지정할 수 있습니다 . 폴더 이름을 파싱하여 final 다음에 텍스트가 있는지 확인합니다 . 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 많이 사용하는 웹 서버를 실행 중일 수 있으며 일부 게시 된 데이터의 유효성을 확인하려고합니다. 필요한 것보다 2-3 배 큰 리소스를 묶는 잘못된 데이터를 원하지 않습니다.
예제 3 사용자가 입력 한 검색 표현식을 구문 분석하고있을 수 있습니다.
그들이 GUID에 들어가면 특별히 처리하고 싶습니다 (예 : 해당 객체 검색 또는 응답 텍스트에서 특정 검색어를 강조 표시하고 형식 지정).
업데이트 3-성능 벤치 마크
10,000 개의 좋은 Guid와 10,000 개의 나쁜 Guid를 변환하는 테스트.
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
추신 : 나는 질문을 정당화 할 필요가 없습니다.
답변
성능 벤치 마크
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 (가장 빠른) 답변 :
/// <summary>
/// Attempts to convert a string to a guid.
/// </summary>
/// <param name="s">The string to try to convert</param>
/// <param name="value">Upon return will contain the Guid</param>
/// <returns>Returns true if successful, otherwise false</returns>
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
{
/// <summary>
/// This function converts a string generated by the StringFromCLSID function back into the original class identifier.
/// </summary>
/// <param name="sz">String that represents the class identifier</param>
/// <param name="clsid">On return will contain the class identifier</param>
/// <returns>
/// Positive or zero if class identifier was obtained successfully
/// Negative if the call failed
/// </returns>
[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);
답변
.net 4.0이 사용 가능하면을 사용할 수 있습니다 Guid.TryParse()
.
답변
당신은 이것을 좋아하지 않을 것입니다. 그러나 예외를 잡는 것이 느리다고 생각하게 만드는 것은 무엇입니까?
성공적인 GUID와 비교할 때 GUID 구문 분석에 실패한 횟수는 몇 번입니까?
내 조언은 방금 만든 기능을 사용하고 코드를 프로파일 링하는 것입니다. 이 기능은 진정으로 핫스팟 것을 발견 할 경우 다음 하지만 전에 그것을 해결.
답변
.NET 4.0에서는 다음과 같이 작성할 수 있습니다.
public static bool IsValidGuid(string str)
{
Guid guid;
return Guid.TryParse(str, out guid);
}
답변
최소한 다음과 같이 다시 작성합니다.
try
{
value = new Guid(s);
return true;
}
catch (FormatException)
{
value = Guid.Empty;
return false;
}
SEHException, ThreadAbortException 또는 기타 치명적이거나 관련이없는 것들에 대해 “유효하지 않은 GUID”라고 말하고 싶지 않습니다.
업데이트 : .NET 4.0부터 Guid에 사용할 수있는 새로운 메소드가 있습니다.
실제로, 그것들은 try-catch를 사용하여 내부적으로 “순진하게”구현되지 않았다는 사실 만 사용해야합니다.
답변
Interop은 예외를 잡는 것보다 느립니다.
10,000 명의 길드가있는 행복한 길에서
Exception: 26ms
Interop: 1,201ms
불행한 길에서 :
Exception: 1,150ms
Interop: 1,201ms
더 일관되지만 느리게 느립니다. 처리되지 않은 예외 만 위반하도록 디버거를 구성하는 것이 더 나을 것 같습니다.
답변
글쎄, 여기에 필요한 정규 표현식이 있습니다 …
^[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가 많지 않기를 바랍니다.