I am new and C#. i want to automatically generate a unique number inside a text box which i can use as a reference number to a form that does asset registration. this reference number will be used as a unique identifier to each asset registered and also given to the asset owner for reference's sake.
To do this, you can use a Guid (globally unique identifier) The chance that the value of the new Guid will be all zeros or equal to any other Guid is very low.
public static void Main()
{
Guid g = Guid.NewGuid();
Console.WriteLine(g);
}
You cand find more about this here:
http://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx
Have you considered using the GUID's they are pretty easy to generate and reasonably unique?
// This code example demonstrates the Guid.NewGuid() method.
using System;
class Sample
{
public static void Main()
{
Guid g;
// Create and display the value of two GUIDs.
g = Guid.NewGuid();
Console.WriteLine(g);
Console.WriteLine(Guid.NewGuid());
}
}
/*
This code example produces the following results:
0f8fad5b-d9cb-469f-a165-70867728950e
7c9e6679-7425-40de-944b-e07fc1f90ae7
*/
You can use a Guid.
Guid temp;
temp = Guid.NewGuid();
textBox1.Text = temp.ToString().Replace("-", "");
But be aware. A real uniqe number generation is impossible.
There are other ways like the Random class
You can use TimeStamp along with the new GUID.
string uniqueKey = string.Concat(DateTime.Now.ToString("yyyyMMddHHmmssf"), Guid.NewGuid().ToString());
If you really need a number intead of string as a unique key then you can use only time stamp with following stratergy.then it will unique with any given time,Lock to ensure that no two threads run your code at the same time. Thread.Sleep to ensure that you get two distinct times at the tenth of second.
static object lockerObject = new object();
static string GetUniqueKey()
{
lock (lockerObject)
{
return DateTime.Now.ToString("yyyyMMddHHmmssf");
Thread.Sleep(100);
}
}
Or i found a way to do it without time stamp from here as follows.
public long GetUniqueKey()
{
byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToInt64(buffer, 0);
}
Related
I am trying to generate unique integer Ids that can be used from multiple threads.
public partial class Form1 : Form
{
private static int sharedInteger;
...
private static int ModifySharedIntegerSingleTime()
{
int unique = Interlocked.Increment(ref sharedInteger);
return unique;
}
SimulateBackTestRow1()
{
while (true)
{
int num = ModifySharedIntegerSingleTime();
}
}
SimulateBackTestRow2()
{
while (true)
{
int num = ModifySharedIntegerSingleTime();
}
}
Task modifyTaskOne = Task.Run(() => SimulateBackTestRow1());
Task modifyTaskTwo = Task.Run(() => SimulateBackTestRow2());
However, when code that takes a unique number that has not been used before gets passed a number that was acquired by ModifySharedIntegerSingleTime, I am getting collisions with numbers that are not unique.
What is the correct way to get unique int Ids in a thread-safe way?
You only have 2^32 unique values with an integer. Since you're generating values as quickly as you can in a loop, it wont take you long to generate more than the ~4 billion values you need to have run out and start returning values you've already used and causing collisions. Either you have some bug in your program that results in you generating more new values than you actually need, or you need to use a type that has more values, such as a long or GUID.
c# Generate Random number passing long as a seed instead of int32, but l need to pass phone numbers or accounts number
https://learn.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8#System_Random__ctor_System_Int32_
Please suggest any reliable NuGet package which does this or any implementation who has already done something like this.
I need to pass the complete PhoneNumber as the seed which I'm able to do in python but not with C# and my code stack is all in C#
using System;
public class Program
{
public static void Main()
{
int seed = 0123456789;
Random random = new Random(seed);
double result = random.NextDouble();
Console.WriteLine(result);
}
}
Some insights on my requirements and what I'm trying to achieve:
1)We're doing this for A/B testing and todo data analysis on the
experience of two services.
2)When a request comes with
phoneNumber based on random.NextDouble() there is a preset percentage
which we use to determine whether to send a request to service A or
service B
3)For example, let's says the request comes and falls
under >0.5 then we direct the request to service A and the next time
the request with the same phone number comes in it will be >0.5 and
goes service A since the seed is a unique hash of phoneNumber.
The method GetHashCode() belongs to Object class, it has nothing to do with random number generation. Please read here (https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.8). The documentation clearly states that it is possible to get collisions specially if input is consistent.
The method HashAlgorithm.ComputeHash (documented here - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hashalgorithm.computehash?view=netframework-4.8) calculates the hash for a given value, but it is consistent in nature, i.e. if input is same, generated output is also same. Obviously this is not the desired output (I assume). I have attached the sample code I tried to generate this.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
while (true)
{
Console.WriteLine("Enter a 9 digit+ number to calculate hash");
var val = Console.ReadLine();
long target = 0;
bool result = long.TryParse(val,out target);
if (result)
{
var calculatedHash = OutputHash(target);
Console.WriteLine("Calculated hash is : " + calculatedHash);
}
else
{
Console.WriteLine("Incorrect input. Please try again.");
}
}
}
public static string OutputHash(long number)
{
string source = Convert.ToString(number);
string hash;
using (SHA256 sha256Hash = SHA256.Create())
{
hash = GetHash(sha256Hash, source);
Console.WriteLine($"The SHA256 hash of {source} is: {hash}.");
Console.WriteLine("Verifying the hash...");
if (VerifyHash(sha256Hash, source, hash))
{
Console.WriteLine("The hashes are the same.");
}
else
{
Console.WriteLine("The hashes are not same.");
}
}
return hash;
}
private static string GetHash(HashAlgorithm hashAlgorithm, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
var sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
// Verify a hash against a string.
private static bool VerifyHash(HashAlgorithm hashAlgorithm, string input, string hash)
{
// Hash the input.
var hashOfInput = GetHash(hashAlgorithm, input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
return comparer.Compare(hashOfInput, hash) == 0;
}
I agree with #Knoop 's comment above that you might end up with same integer mapping to multiple long number input values.
If you are looking for a 'pure' random number generator with long value as seed, you don't have a choice but to go for third party libraries (or implementing your own custom algorithm). However, rather than getting into such complexities, simple
Guid g = Guid.NewGuid();
should do the trick (https://learn.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=netframework-4.8).
Documentation (https://learn.microsoft.com/en-gb/windows/win32/api/combaseapi/nf-combaseapi-cocreateguid?redirectedfrom=MSDN )says that even this can end up having collisions but chances are very minimal.
Finally, this sounds like potential duplicate of .NET unique object identifier
take the hash of the phone number, eg:
var phoneNumber = 123456789L;
var seed = phoneNumber.GetHashCode();
This means that for the same phoneNumber you will get the same sequence. It also means that for some phone numbers you will get identical sequences, but that is going to be slim. And it might be different on different .net runtimes as commented, but you might not care.
Not sure why you want to, but I there are reasons, e.g. test code
Is there a way to generate unique alphanumeric key (12 digits) to be used in URLs in C#? I have a set of strings that are unique from each other, but cannot use them directly as they might change, so the URL will break. I have couple of approaches -
a) Use the primary key of database table itself which corresponds to the row with above set of strings, but this seems like a security issue as it will expose db structure.
b) Use Guid, but then again it is not dependent on the data.
Any help will be appreciated.
Short Answer: No.
What you're trying is not possible. You would have to keep track of the ids that you've already created. This is what a database does with index columns that increment. I also understand that URL shortening tools take new keys from a pool of generated unique ones.
All that being said, something like this DotNetFiddle might work and so might some of the other answers.
In the fiddle, we're hashing the primary key in the first example. Since only the full hash is computationally infeasible not to be unique per input, and since we're using a sub-string of the hash, the uniqueness is not guaranteed, but it may be close.
Here is what MSDN has to say about hash uniqueness.
A cryptographic hash function has the property that it is computationally infeasible to find two distinct inputs that hash to the same value.
In the second example, we're using time, and incrementing time is guaranteed to be unique as far as I know, so this will work if you can rely on the time being accurate. But if you're going to be relying on an external resource like the server time, then maybe you should be using an auto-incrementing index in a database table or a simple flat file.
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
UseAHash();
UseTime();
}
public static void UseAHash()
{
var primaryKey = 123345;
HashAlgorithm algorithm = SHA1.Create();
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(primaryKey.ToString()));
StringBuilder sb = new StringBuilder();
for (var i = 0; i < 6; ++i)
{
sb.Append(hash[i].ToString("X2"));
}
Console.WriteLine(sb);
}
public static void UseTime()
{
StringBuilder builder = new StringBuilder();
// use universal to avoid daylight to standard time change.
var now = DateTime.Now.ToUniversalTime();
builder.Append(now.DayOfYear.ToString("D3"));
builder.Append(now.Hour.ToString("D2"));
builder.Append(now.Minute.ToString("D2"));
builder.Append(now.Second.ToString("D2"));
builder.Append(now.Millisecond.ToString("D3"));
Console.WriteLine("Length: " + builder.Length);
Console.WriteLine("Result: " + builder);
}
}
You can use the key from the database to seed a random generator, and use that to create a key:
int id = 42;
string chars = "2345679abcdefghjkmnpqrstuvwxyz";
Random rnd = new Random(id);
string key = new String(Enumerable.Range(0, 12).Select(n => chars[rnd.Next(chars.Length)]).ToArray());
Note: This is not guaranteed to be unique. I tested the values from 1 to 10000000 though, and there are no duplicates there.
Simple. Create a new GUID, assign it an entity from the database, then add it to a database table.
public class FooGuid
{
[Key] public Guid Url { get; set; }
public Foo Foo { get; set; }
}
Guid urlpart = ...
Foo foo = dbContext.FooGuids
.Where(f => f.Url == urlpart)
.Select(f => f.Foo)
.Single();
am started testing hash function on the uniqueness of the generated HashCodes with my algorithm. And i wrote next text class to test when the same hashCode will be generated.
class Program
{
static void Main(string[] args)
{
var hashes = new List<int>();
for (int i = 0; i < 100000; i++)
{
var vol = new Volume();
var code = vol.GetHashCode();
if (!hashes.Contains(code))
{
hashes.Add(code);
}
else
{
Console.WriteLine("Same hash code generated on the {0} retry", hashes.Count());
}
}
}
}
public class Volume
{
public Guid DriverId = Guid.NewGuid();
public Guid ComputerId = Guid.NewGuid();
public int Size;
public ulong VersionNumber;
public int HashCode;
public static ulong CurDriverEpochNumber;
public static Random RandomF = new Random();
public Volume()
{
Size = RandomF.Next(1000000, 1200000);
CurDriverEpochNumber ++;
VersionNumber = CurDriverEpochNumber;
HashCode = GetHashCodeInternal();
}
public int GetHashCodeInternal()
{
unchecked
{
var one = DriverId.GetHashCode() + ComputerId.GetHashCode() * 22;
var two = (ulong)Size + VersionNumber;
var result = one ^ (int)two;
return result;
}
}
}
GUIDs fields DriverId, ComputerId and int Size are random.
I assumed that at some time we will generate the same hash-code. You know it will break work with big collections. Magic was in fact that the retry number when the duplicated
hash code is generated are the same! I run sample code for several time and got near the same result: firs run duplicate on 10170 retry, second on 7628, third 7628
and again and again on 7628. Some times i got a little bit others results. Bu in most cases it was on 7628.
It has no explanations for me.
Is it error in . NET random generator or what?
Thanks all. Now it is clear the was bug in my code (Matthew Watson). I had to call GetHashCodeIntelrnal() and not GetHashCode(). The best GetHashCode unique results gave me:
public int GetHashCodeInternal()
{
unchecked
{
var one = DriverId.GetHashCode() + ComputerId.GetHashCode();
var two = ((ulong)Size) + VersionNumber;
var result = one ^ (int)two << 32;
return result;
}
}
Bu still on near 140 000 it give same code... i think it is not good because ve have collections near 10 000...
If you change your Console.WriteLine() to also print Volume.Size like so:
Console.WriteLine("Same hash code generated on the {0} retry ({1})", hashes.Count, vol.Size);
you will see that although hashes.Count is always the same for the first collision, vol.Size is usually different.
This seems to rule out the random number generator causing this issue - it looks like some strange property of GetHashCodeInternal().
Closer inspection reveals that you are calling the wrong hash code function.
This line: var code = vol.GetHashCode();
Should be: var code = vol.HashCode;
Try that instead! Because at the moment you are calling the default .Net GetHashCode() which is not doing what you want at all.
You will need to pass in the random number generator, having created a single one to be reused, as currently you're creating new instances of them too close together which results in the same seed being used, and hence the same sequence of numbers coming out.
Your results will randomly come out seemingly random at points where the seed is generated from the next ticks/seconds of the seed date. So, just incidental, really.
In the application, when special types of objects are created, I need to generate a unique-id for each of them. The objects are created thro' a factory and have a high possibility of being created in a 'bulk' operation. I realize that the "Random" from the framework is not so 'random' after all, so I tried appending the time-stamp as follows:
private string GenerateUniqueId()
{
Random randomValue = new Random();
return DateTime.Now.Ticks.ToString() + randomValue.Next().ToString();
}
Unfortunately, even this does not work. For objects that are created in rapid succession, I generate the same Unique Id :-(
Currently, I am implementing it in a crude way as follows:
private string GenerateUniqueId()
{
Random randomValue = new Random();
int value = randomValue.Next();
Debug.WriteLine(value.ToString());
Thread.Sleep(100);
return DateTime.Now.Ticks.ToString() + value.ToString();
}
Since this is not a very large application, I think a simple and quick technique would suffice instead of implementing an elaborate algorithm.
Please suggest.
A GUID is probably what you're looking for:
private string GenerateUniqueId()
{
return Guid.NewGuid().ToString("N");
}
If you want a smaller, more manageable ID then you could use something like this:
private string GenerateUniqueId()
{
using (var rng = new RNGCryptoServiceProvider())
{
// change the size of the array depending on your requirements
var rndBytes = new byte[8];
rng.GetBytes(rndBytes);
return BitConverter.ToString(rndBytes).Replace("-", "");
}
}
Note: This will only give you a 64-bit number in comparison to the GUID's 128 bits, so there'll be more chance of a collision. Probably not an issue in the real world though. If it is an issue then you could increase the size of the byte array to generate a larger id.
Assuming you do not want a GUID, First option would be a static field, and interlocked:
private static long lastId = 0
private static long GetNextId() {
return Interlocked.Increment(ref lastId);
}
If you want something based on time ticks, remember the last value and if the same manually increment and save; otherwise just save:
private static long lastTick = 0;
private static object idGenLock = new Object();
private static long GetNextId() {
lock (idGenLock) {
long tick = DateTime.UtcNow.Ticks;
if (lastTick == tick) {
tick = lastTick+1;
}
lastTick = tick;
return tick;
}
}
(Neither of these approaches will be good with multiple processes.)
In your comments Codex you say use the unique ID as a file name. There is a specific function for generating cryptographically secure file names, Path.GetRandomFileName()
As it's cryptographically secure these would be unique even in batch operations. The format is a little horrible though as they're optimised for filenames, but it may work for other references as well.
Why can't your factory (which is presumably single-threaded) generate sequential unique integers? If you expected Random() to work, why not Guid() (or whatever is equivalent)?
If you're going to resort to coding your own UUID-generator, make sure you salt the generator.
I suggest you check out the open source package ossp-uuid, which is an ISO-C API and CLI for generating Universally Unique Identifiers.