In C# applications randomness is generally implemented using the System.Random class.
This article is an excellent introduction to the subject.
When becoming familiar with a library class it is always worth studying the documentation for properties and methods and their overloads.
The coding exercise highlighted a number of issues:
Random.Next() can generate a range of integersRandom.Double() can generate a double between 0 and 1Next...(), Double() and Sample() are exclusive so that Random.Next(1,19) will yield values from 1 to 18 but not 19.There are 3 patterns for implementing the last point:
Random.NextDouble() and multiplying by 100. This piece discusses making random selections from an array.System.Random and override the Sample() method.System.Random as a member of a class of your own, for example to generate booleans.The numbers generated by Random are not guaranteed to be unique.
It is recommended that you instantiate System.Random as a static member. But, note that it is not thread safe.
You may see documentation discouraging the use of seedless constructors. This mostly applies to .NET Framework rather than .NET Core (which is what Exercism uses). For the full story read this.
You are advised not to use System.Random for crypto or security. See this provider and this number generator.
When applied in the context of library APIs "not thread safe" is simply shorthand for saying that, if you are likely to access instances of the class through multiple concurrent threads, you should provide your own thread synchronization mechanisms or, in the case of collections, look at the possibility of using a concurrent version of the class. In the absence of these precautions, race conditions are likely to occur. If your code base does not use multiple threads, and is not likely to, then this warning is of little concern.