2011-01-25 32 views
6

Vì vậy, tôi đã viết một nhỏ và, từ những gì tôi nghĩ ban đầu, phương pháp dễ dàng trong C#. phương pháp tĩnh này có nghĩa là để được sử dụng như một máy phát điện mật khẩu gợi ý đơn giản, và mã trông như thế này:Chức năng C# tĩnh của tôi đang chơi trò chơi với tôi ... hoàn toàn lạ!

public static string CreateRandomPassword(int outputLength, string source = "") 
{ 
    var output = string.Empty; 

    for (var i = 0; i < outputLength; i++) 
    { 
    var randomObj = new Random(); 
    output += source.Substring(randomObj.Next(source.Length), 1); 
    } 

    return output; 
} 

tôi gọi chức năng này như sau:

var randomPassword = StringHelper.CreateRandomPassword(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"); 

Bây giờ, phương pháp này hầu như luôn luôn trả về các chuỗi ngẫu nhiên như "AAAAAA", "BBBBBB", "888888" v.v., ở đây tôi nghĩ nó sẽ trả về các chuỗi như "A8JK2A", "82mOK7", v.v.

Tuy nhiên, đây là phần khó hiểu; Nếu tôi đặt một điểm ngắt và bước qua đường lặp này bằng dòng, tôi sẽ nhận lại đúng loại mật khẩu. Trong 100% các trường hợp khác, khi Im không gỡ lỗi, nó cho tôi crap như "AAAAAA", "666666", v.v.

Làm cách nào có thể? Bất kỳ đề xuất được đánh giá rất nhiều! :-)

BTW, hệ thống của tôi: Visual Studio 2010, C# 4.0, ASP.NET MVC 3 RTM dự án w/ASP.NET Development Server. Chưa thử nghiệm mã này trong bất kỳ môi trường nào khác.

+0

Tôi không biết liệu nó có gây ra vấn đề của bạn hay không, nhưng có thể bạn không muốn tạo một trường hợp ngẫu nhiên mới trên mỗi lần lặp. Bạn nên làm điều này một lần trước khi vòng lặp. Phương thức khởi tạo mặc định của Random sử dụng Environment.TickCount làm một hạt giống. Ngoài ra, giá trị mặc định của bạn cho nguồn không có ý nghĩa nhiều vì tôi nghĩ chuỗi rỗng sẽ gây ra lỗi trong cuộc gọi đến Chuỗi con. –

+0

Bạn nói đúng, ông Putty! Ban đầu tôi đã có chuỗi "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" được đặt ở đó. Cảm ơn! – CoderBang

Trả lời

15

Di chuyển tuyên bố cho randomObj bên ngoài vòng lặp. Khi bạn đang gỡ lỗi nó, nó tạo ra nó với một hạt giống mới mỗi lần, bởi vì có đủ sự khác biệt về thời gian cho hạt giống khác nhau. Nhưng khi bạn không gỡ lỗi, thời gian hạt giống về cơ bản là giống nhau cho mỗi lần lặp của vòng lặp, do đó, nó mang lại cho bạn cùng một giá trị bắt đầu mỗi lần.

Và một chút nhỏ - đó là thói quen tốt để sử dụng StringBuilder chứ không phải chuỗi cho loại điều này, vì vậy bạn không phải khởi tạo lại không gian bộ nhớ mỗi lần bạn thêm ký tự vào chuỗi .

Nói cách khác, như thế này:

public static string CreateRandomPassword(int outputLength, string source = "") 
{ 
    var output = new StringBuilder(); 
    var randomObj = new Random(); 
    for (var i = 0; i < outputLength; i++) 
    { 
    output.Append(source.Substring(randomObj.Next(source.Length), 1)); 
    } 
    return output.ToString(); 
} 
+0

Ah, điều đó giải thích nó! Cảm ơn rất nhiều Ken! :) – CoderBang

+0

Cá nhân tôi đã đi cho một char [] (thay vì StringBuilder) và snagging char từ nguồn thông qua các chỉ số, nhưng khá giống nhau. –

+2

+1. Chỉ cần một lưu ý khác, nó gần như luôn luôn tốt hơn để khai báo các đối tượng ngẫu nhiên càng ít càng tốt. Tôi thậm chí còn đi xa đến mức giải nén tờ khai vào một trường tĩnh. Nếu bạn đã có hai chủ đề nhấn chức năng này cùng một lúc, có một cơ hội bạn sẽ nhận được chính xác cùng một mật khẩu nhổ ra. – Rob

4

Các hành vi bạn đang nhìn thấy là vì Randomthời gian dựa trên, và khi bạn không gỡ lỗi nó bay qua tất cả 5 lần lặp đồng thời điểm (nhiều hơn hoặc ít hơn). Vì vậy, bạn đang yêu cầu số ngẫu nhiên đầu tiên ra khỏi cùng một hạt giống. Khi bạn đang gỡ lỗi, phải mất đủ thời gian để có được một hạt giống mới mỗi lần.

Di chuyển tuyên bố Random bên ngoài vòng lặp:

var randomObj = new Random(); 
for (var i = 0; i < outputLength; i++) 
{ 
    output += source.Substring(randomObj.Next(source.Length), 1); 
} 

Bây giờ bạn đang di chuyển về phía trước 5 bước đi từ một hạt giống ngẫu nhiên thay vì di chuyển 1 bước ra khỏi hạt giống ngẫu nhiên cùng 5 lần .

2

Bạn đang tạo một thể hiện ngẫu nhiên mới() trên mỗi lần lặp qua vòng lặp với một hạt giống phụ thuộc thời gian mới. Do độ chi tiết của đồng hồ hệ thống và tốc độ của CPU hiện đại, điều này đảm bảo rằng bạn khởi động lại chuỗi giả ngẫu nhiên lặp đi lặp lại với cùng một hạt giống.

Hãy thử một cái gì đó như sau, tuy nhiên nếu bạn đang single-ren, bạn có thể yên tâm bỏ qua các khóa():

private static Random randomBits = new Random() ; 
public static string CreateRandomPassword(int outputLength, string source = "") 
{ 
    StringBuilder sb = new StringBuilder(outputLength) ; 
    lock (randomBits) 
    { 
    while (sb.Length < outputLength) 
    { 
     sb.Append(randomBits.Next(source.Length) , 1) ; 
    } 
    } 
    return sb.ToString() ; 
} 

Bạn chỉ nhanh chóng RNG một lần. Mỗi bit rút ra từ cùng một RNG, vì vậy nó sẽ hoạt động giống như một nguồn entropy.Nếu bạn cần lặp lại để kiểm tra, hãy sử dụng quá tải Hàm tạo ngẫu nhiên cho phép bạn cung cấp hạt giống. Cùng một hạt giống == cùng một chuỗi giả ngẫu nhiên.

Các vấn đề liên quan