2010年8月30日 星期一

Guid TryParse

日前在專案執行上突然有個需求,就是要對輸入的資料做Guid格式的驗證,
一開始就下意識去找Guid下的TryParse方法,這個時候才發現 .NET 3.5(2.0) 的Guid是沒有TryParse方法…
細查下去才知道,Guid的TryParse與Parse方法在 .NET 4.0才新加入(小弟真是才疏學淺…汗顏…),
之前經常使用Guid,卻甚少對Guid的格式驗證稍加留意。


Guid,Globally Unique Identifier 全域唯一識別項
Wiki : Globally unique identifier

Guid 結構
GUID 是一個 128 位元的整數 (16 位元組),可以在需要唯一識別項時用於所有電腦和網路。這種識別項被複製的可能性非常低。

在程式設計中會常常在編號的使用上,因為使用GUID不會有重複編號的問題存在(不是不會有,而是機率相當低),
所以在類別設計時,在類別的ID (Primary Key) 屬性上,我會優先使用GUID來做為Class中主鍵資料的型別,
而在SQL Server的Table 欄位的型別就是使用uniqueidentifier

在 .NET Framework 2.0 版本並沒有提供 TryParse, Parse 的Method,
如果時常需要使用到Guid的檢測時,就必須另外編寫TryParse的方法,以利日後的程式編寫。

.NET Framework 2.0 的GUID成員之公用方法
image

Guid還有幾種格式的區別,分別為:"N"、"D"、"B"、"P"、"X"

以下顯示 format 參數已接受的格式規範表示。
0"代表一個數字,連字號 ("-")、括號 ("{","}"),及括號 ("(",")") 如下所示。

N
32 位數字:00000000000000000000000000000000
D
以連字號分隔的 32 位數字:00000000-0000-0000-0000-000000000000
B
以連字號分隔並以大括號括起來的 32 位數字:{00000000-0000-0000-0000-000000000000}
P
以連字號分隔並以括號括起來的 32 位數字:(00000000-0000-0000-0000-000000000000)
X
括號中包含四個十六進位值,其中第四個值是八個十六進位值的子集,同樣包含在括號中:
{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}

先來看看在4.0之前對GUID進行TryParse的方法
Reference by: http://connect.microsoft.com/VisualStudio/feedback/details/94072/guid-tryparse
#region -- GuidTryParse --
 
/// <summary>
/// GUIDs the try parse.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <param name="output">The output.</param>
/// <returns></returns>
public static bool GuidTryParse(string candidate, out Guid output)
{
if (candidate == null) throw new ArgumentNullException("s");
 
Regex format = new Regex(string.Concat(
"^[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}(}})$"
));
 
Match match = format.Match(candidate);
output = (match.Success) ? new Guid(candidate) : Guid.Empty;
return match.Success;
}
 
#endregion


實際的使用
image

程式碼


protected void button1_Click(object sender, EventArgs e)
{
// TryParse Correct GUID
System.Guid check = System.Guid.NewGuid();
bool result = Test.GuidTryParse(text1.Text.Trim(), out check);
label1.Text = result.ToString();
}
 
protected void button2_Click(object sender, EventArgs e)
{
// TryParse Wrong GUID
System.Guid check = System.Guid.NewGuid();
bool result = Test.GuidTryParse(text2.Text.Trim(), out check);
label2.Text = result.ToString();
}

上面是 .NET Framework 3.5 以前的方法

而在 .NET Framework 4.0 就已經將Parse, TryParse等方法加入

.NET Framework 4.0 的GUID成員之公用方法

image

上面的各種方法成員中,可以看到四個方法:Parse、ParseExact、TryParse、TryParseExact,

而ParseExact與TryParseExact則是可以讓我們指定哪一種 Guid的格式。


直接看 .NET 4.0下Guid的TryParse與TryParseExact的單元測試

[TestMethod]
public void Guid_TryParse_Test()
{
System.Guid testGuid1 = System.Guid.NewGuid();
string guidB = testGuid1.ToString("B");
 
Assert.IsTrue(System.Guid.TryParse(guidB, out testGuid1));
Assert.IsTrue(System.Guid.TryParseExact(guidB, "B", out testGuid1));
Assert.IsFalse(System.Guid.TryParseExact(guidB, "X", out testGuid1));
 
System.Guid testGuid2 = System.Guid.Parse(guidB);
string guidX = testGuid2.ToString("X");
 
Assert.IsTrue(System.Guid.TryParse(guidX, out testGuid2));
Assert.IsTrue(System.Guid.TryParseExact(guidX, "X", out testGuid2));
Assert.IsFalse(System.Guid.TryParseExact(guidX, "B", out testGuid2));
} 

或許有人會說…怎麼不用以下的方法來解決呢?

private bool IsGuid(string source)
{
if (string.IsNullOrEmpty(source))
{
return false;
}
try 
{
System.Guid test = new System.Guid(source);
return true;
}
catch
{
return false;
}
}

這是因為「try … catch …」,雖然在Catch區段才會對效能產生影響,雖然效能的影響不是很嚴重,

但是濫用try catch來做檢測,實在不是一個認知正確的coding作為,

應該是去用正確的方式去做對的事,而不能只是要將事情去做對而已。



Jeff隨手記 - Try Catch Finally概述

黑暗執行緒 - Try Catch Block是否會影響效能?



所以…

如果在資料主鍵沒有特殊需求,否則建議使用Guid來做為主鍵的型別,

而且在於資料安全上會比一般用int然後自動增值的主鍵要來得高,

使用 int自動增值的主鍵,容易引來有心人士對系統的「特別關注」,因為數字資料實在是太容易做改變了。



延伸閱讀:

The Gospel of the GUID

Will 保哥 - 深入瞭解 GUID 與為什麼要用 GUID

MSDN : 使用 GUID




沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。

最近的留言