2011-04-15 167 views
1
private static Int64 NextInt64(Random rnd) 
{  
    var buffer = new byte[sizeof(Int64)];  
    rnd.NextBytes(buffer);  
    return BitConverter.ToInt64(buffer, 0); 
} 

上述方法是從該線程:Generate random values in C#哪種方式更好地調用這個id生成方法?

它將在一個抽象事件類被用來產生獨特EVENTID。該類將被頻繁使用,因爲我們需要發送大量事件。當我調用上述事件類的構造方法,該方法的選擇是從性能和的視圖唯一值點更好:

  1. 創建Random對象與new並把它傳遞到每個時間以上的方法;
  2. 在最初創建一個靜態的Random對象,並在需要時使用它重複調用上述方法。
+3

爲什麼不使用GUID,然後`Guid.NewGuid()`? (一個評論,因爲它不回答你的問題 - 這是關於這個代碼的隨機值的有效性) – 2011-04-15 15:46:30

+2

這是一個有效的評論 - 使用隨機生成**唯一的**號碼是一個糟糕的決定。 – MattDavey 2011-04-15 15:51:43

+1

我不能強調使用隨機數字作爲「唯一密鑰」的愚蠢行爲。使用64位隨機數,在約6.1億個項目之後有1%的機會產生副本。這是*可能*連續兩次生成相同的數字。我強烈建議你使用其他方法來生成一個唯一的密鑰。 – 2011-04-15 16:32:20

回答

3

你最好創建一個Random實例並多次使用它。你會通過這種方式獲得更好的「隨機性」。

如果您查看微軟的文檔here,您會看到兩個隨機實例產生完全相同的數字。

獲得「更好」隨機數的另一種方法是提供種子。有些人把當前時間作爲一個整數來獲得一個非常獨特的種子。

+3

無參數構造函數將當前時間(來自`Environment.TickCount`)作爲種子傳遞。使用其他構造函數的最常見原因是,如果要確保每次都生成相同的隨機數序列,那麼通常用於測試目的。 – 2011-04-15 16:13:09

2
  • 無論如何,你需要選項2),否則你的隨機數將是相同的。見this
  • 你可以把這個方法爲extenison,

像這樣:

public static class Helpers 
{ 
    public static Int64 NextInt64(this Random rnd) { ... } 
} 

但是......

它會在一個抽象事件類可用於生成唯一的事件ID。

不,這不會生成唯一的ID。準備好碰撞。

使用一個簡單的計數器(nextId)或GUID

1

1將導致與隨機性的問題,除非你每次給它一個獨特的種子。更不用說對垃圾收集器施加額外的壓力。

2是一個更好的選擇 - 隨機類是設計生成一個隨機數序列,而不僅僅是一個。所以雖然最好有一個Random實例,但它不一定需要用一個靜態屬性訪問,它可以以任何方式公開。

2

系統Guid結構正是爲了這個目的。而不是試圖傳遞一個看似隨機的對象,而是傳遞一個guid結構作爲參數。

private static Guid NextIntGuid() 
{ 
    return Guid.NewGuid(); 
} 

顧名思義,它已經代表一個全球唯一的標識符。此外,如果您堅持使用隨機數字,請在System.Security.Cryptography名稱空間內使用RandomNumberGenerator。如果足夠大,你的隨機數將幾乎是唯一的:

byte[] random = new Byte[128]; 

//RNGCryptoServiceProvider is an implementation of a random number generator. 
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
rng.GetBytes(random); // The array is now filled with cryptographically strong random bytes.