Guid TryParse

  • 900
  • 0
  • C#
  • 2010-08-31

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

 

日前在專案執行上突然有個需求,就是要對輸入的資料做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

純粹是在寫興趣的,用寫程式、寫文章來抒解工作壓力