Is C# Random Number Generator thread safe? - c#

Is C#'s Random.Next() method thread safe?

No, using the same instance from multiple threads can cause it to break and return all 0's. However, creating a thread-safe version (without needing nasty locks on every call to Next()) is simple. Adapted from the idea in this article:
public class ThreadSafeRandom
{
private static readonly Random _global = new Random();
[ThreadStatic] private static Random _local;
public int Next()
{
if (_local == null)
{
int seed;
lock (_global)
{
seed = _global.Next();
}
_local = new Random(seed);
}
return _local.Next();
}
}
The idea is to keep a separate static Random variable for each thread. Doing that in the obvious way fails, however, because of another issue with Random - if multiple instances are created at nearly the same time (within about 15ms), they will all return the same values! To fix this, we create a globally-static Random instance to generate the seeds used by each thread.
The above article, by the way, has code demonstrating both of these issues with Random.

There's nothing special done in the Next method to achieve thread safety. However, it's an instance method. If you don't share instances of Random across different threads, you don't have to worry about state corruption within an instance. Do not use a single instance of Random across different threads without holding an exclusive lock of some sort.
Jon Skeet has a couple nice posts on this subject:
StaticRandom
Revisiting randomness
As noted by some commentators, there is another potential problem in using different instances of Random that are thread-exclusive, but are seeded identically, and therefore induce the identical sequences of pseudorandom numbers, because they may be created at the same time or within close temporal proximity of each other. One way to alleviate that issue is to use a master Random instance (which is locked by a single thread) to generate some random seeds and initialize new Random instances for every other thread to use.

The offical answer from Microsoft is a very strong no. From http://msdn.microsoft.com/en-us/library/system.random.aspx#8:
Random objects are not thread safe. If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a thread-safe way, calls to methods that return random numbers return 0.
As described in the docs, there is a very nasty side effect that can happen when the same Random object is used by multiple threads: it just stops working.
(i.e. there is a race condition which when triggered, the return value from the 'random.Next....' methods will be 0 for all subsequent calls.)

No, it's not thread safe. If you need to use the same instance from different threads, you have to synchronise the usage.
I can't really see any reason why you would need that, though. It would be more efficient for each thread to have their own instance of the Random class.

Another thread safe way is to use ThreadLocal<T> as follows:
new ThreadLocal<Random>(() => new Random(GenerateSeed()));
The GenerateSeed() method will need to return a unique value each time it is called to assure that the random number sequences are unique in each thread.
static int SeedCount = 0;
static int GenerateSeed() {
return (int) ((DateTime.Now.Ticks << 4) +
(Interlocked.Increment(ref SeedCount)));
}
Will work for small numbers of threads.

Is C#'s Random.Next() method thread safe?
As was written before, anwer is No. However, starting from .NET6, we have out of box thread-safe alternative: Random.Shared.Next();
See details here: https://learn.microsoft.com/en-us/dotnet/api/system.random.shared?view=net-6.0

For what its worth, here is a thread-safe, cryptographically strong RNG that inherits Random.
The implementation includes static entry points for ease of use, they have the same names as the public instance methods but are prefixed with "Get".
A call to the RNGCryptoServiceProvider.GetBytes is a relatively expensive operation. This is mitigated through the use of an internal buffer or "Pool" to make less frequent, and more efficient use of RNGCryptoServiceProvider. If there are few generations in an application domain then this could be viewed as overhead.
using System;
using System.Security.Cryptography;
public class SafeRandom : Random
{
private const int PoolSize = 2048;
private static readonly Lazy<RandomNumberGenerator> Rng =
new Lazy<RandomNumberGenerator>(() => new RNGCryptoServiceProvider());
private static readonly Lazy<object> PositionLock =
new Lazy<object>(() => new object());
private static readonly Lazy<byte[]> Pool =
new Lazy<byte[]>(() => GeneratePool(new byte[PoolSize]));
private static int bufferPosition;
public static int GetNext()
{
while (true)
{
var result = (int)(GetRandomUInt32() & int.MaxValue);
if (result != int.MaxValue)
{
return result;
}
}
}
public static int GetNext(int maxValue)
{
if (maxValue < 1)
{
throw new ArgumentException(
"Must be greater than zero.",
"maxValue");
}
return GetNext(0, maxValue);
}
public static int GetNext(int minValue, int maxValue)
{
const long Max = 1 + (long)uint.MaxValue;
if (minValue >= maxValue)
{
throw new ArgumentException(
"minValue is greater than or equal to maxValue");
}
long diff = maxValue - minValue;
var limit = Max - (Max % diff);
while (true)
{
var rand = GetRandomUInt32();
if (rand < limit)
{
return (int)(minValue + (rand % diff));
}
}
}
public static void GetNextBytes(byte[] buffer)
{
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
if (buffer.Length < PoolSize)
{
lock (PositionLock.Value)
{
if ((PoolSize - bufferPosition) < buffer.Length)
{
GeneratePool(Pool.Value);
}
Buffer.BlockCopy(
Pool.Value,
bufferPosition,
buffer,
0,
buffer.Length);
bufferPosition += buffer.Length;
}
}
else
{
Rng.Value.GetBytes(buffer);
}
}
public static double GetNextDouble()
{
return GetRandomUInt32() / (1.0 + uint.MaxValue);
}
public override int Next()
{
return GetNext();
}
public override int Next(int maxValue)
{
return GetNext(0, maxValue);
}
public override int Next(int minValue, int maxValue)
{
return GetNext(minValue, maxValue);
}
public override void NextBytes(byte[] buffer)
{
GetNextBytes(buffer);
}
public override double NextDouble()
{
return GetNextDouble();
}
private static byte[] GeneratePool(byte[] buffer)
{
bufferPosition = 0;
Rng.Value.GetBytes(buffer);
return buffer;
}
private static uint GetRandomUInt32()
{
uint result;
lock (PositionLock.Value)
{
if ((PoolSize - bufferPosition) < sizeof(uint))
{
GeneratePool(Pool.Value)
}
result = BitConverter.ToUInt32(
Pool.Value,
bufferPosition);
bufferPosition+= sizeof(uint);
}
return result;
}
}

Since Random isn't thread-safe, you should have one per thread, rather than a global instance. If you're worried about these multiple Random classes being seeded at the same time (i.e. by DateTime.Now.Ticks or such), you can use Guids to seed each of them. The .NET Guid generator goes to considerable lengths to ensure non-repeatable results, hence:
var rnd = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0))

Reimplementation of BlueRaja's answer using ThreadLocal:
public static class ThreadSafeRandom
{
private static readonly System.Random GlobalRandom = new Random();
private static readonly ThreadLocal<Random> LocalRandom = new ThreadLocal<Random>(() =>
{
lock (GlobalRandom)
{
return new Random(GlobalRandom.Next());
}
});
public static int Next(int min = 0, int max = Int32.MaxValue)
{
return LocalRandom.Value.Next(min, max);
}
}

Per documentation
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
http://msdn.microsoft.com/en-us/library/system.random.aspx

Here is a simple solution that doesn't involve creating classes. Hides everything inside an ad-hoc lambda:
private static Func<int, int, int> GetRandomFunc()
{
Random random = new Random();
object lockObject = new object();
return (min, max) =>
{
lock (lockObject)
{
return random.Next(min, max);
}
};
}
In any class that needs a thread safe random generator define
private static readonly Func<int, int, int> GetRandomNext = GetRandomFunc();
Then use it freely inside your class:
int nextRandomValue = GetRandomNext(0, 10);
The radndom function can have different signatures depending what is needed. e.g.
private static Func<int> GetRandomFunc()
{
Random random = new Random();
object lockObject = new object();
return () =>
{
lock (lockObject)
{
return random.Next();
}
};
}

For a thread safe random number generator look at RNGCryptoServiceProvider. From the docs:
Thread Safety
This type is thread safe.

I just created Random instance on a load of threads simultaneously and got unexpected patterns from the results because, presumably, all the seeds were the same.
My solution was to create a thread safe class -
public class StaticRandom
{
static Random rnd = new Random();
public static int GetNext()
{
// random is not properly thread safe
lock(rnd)
{
return rnd.Next();
}
}
}
And then, create a new Random object instance for each thread -
// Take this threads instance seed from the static global version
Random rnd = new Random(StaticRandom.GetNext());

Here's an efficient solution using ThreadLocal:
public class ThreadSafeRandom
{
private static readonly Random _global = new Random();
private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
{
int seed;
lock (_global)
{
seed = _global.Next();
}
return new Random(seed);
});
public static Random Instance => _local.Value;
}
To use, replace:
var random = new Random();
var myNum = random.Next();
With:
var myNum = ThreadSafeRandom.Instance.Next();
This solution has been packaged as a NuGet package with source available on GitHub.
EDIT: Since .NET 6.0 you can use Random.Shared.Next() instead. You can still use the above package which chooses between the above code or Random.Shared with preprocessor directives.

Here is an expanded version of BlueRaja's answer as a static class with comments and all public Random members implemented.
/// <summary>
/// A pseudo-random number generator based on <see cref="Random"/>, but with the following enhancements:
/// <list type="number">
/// <item>Can be safely used from any thread without defaulting to 0.</item>
/// <item>Repeated calls from different threads do not tend to generate identical sequences.</item>
/// </list>
/// </summary>
public static class ThreadSafeRandom
{
private static readonly Random _globalSeeder = new Random();
/// <summary>
/// Holds a separate <see cref="Random"/> instance for each thread.
/// </summary>
[ThreadStatic] private static Random _threadStaticInstance;
/// <summary>
/// Seeds each thread's <see cref="_threadStaticInstance"/> with <see cref="_globalSeeder"/>'s <see cref="Random.Next()"/>.
/// Simply using <see langword="new"/> <see cref="Random()"/> would cause a problem where,
/// if multiple threads' <see cref="Random"/> instances were constructed very close in time,
/// they would end up with the same seed, and therefore identical sequences.
/// </summary>
private static Random GetThreadStaticInstance()
{
if (_threadStaticInstance == null)
{
int seed;
lock (_globalSeeder)
{
seed = _globalSeeder.Next();
}
_threadStaticInstance = new Random(seed);
}
return _threadStaticInstance;
}
/// <inheritdoc cref="Random.Next()"/>
public static int Next() => GetThreadStaticInstance().Next();
/// <inheritdoc cref="Random.Next(int, int)"/>
public static int Next(int minValue, int maxValue) => GetThreadStaticInstance().Next(minValue, maxValue);
/// <inheritdoc cref="Random.Next(int)"/>
public static int Next(int maxValue) => GetThreadStaticInstance().Next(maxValue);
/// <inheritdoc cref="Random.NextDouble()"/>
public static double NextDouble() => GetThreadStaticInstance().NextDouble();
/// <inheritdoc cref="Random.NextBytes(byte[])"/>
public static void NextBytes(byte[] buffer) => GetThreadStaticInstance().NextBytes(buffer);

UPDATED: It is not. You need to either reuse an instance of Random on each consecutive call with locking some "semaphore" object while calling the .Next() method or use a new instance with a guaranteed random seed on each such call. You can get the guaranteed different seed by using cryptography in .NET as Yassir suggested.

The traditional thread local storage approach can be improved upon by using a lock-less algorithm for the seed. The following was shamelessly stolen from Java's algorithm (possibly even improving on it):
public static class RandomGen2
{
private static readonly ThreadLocal<Random> _rng =
new ThreadLocal<Random>(() => new Random(GetUniqueSeed()));
public static int Next()
{
return _rng.Value.Next();
}
private const long SeedFactor = 1181783497276652981L;
private static long _seed = 8682522807148012L;
public static int GetUniqueSeed()
{
long next, current;
do
{
current = Interlocked.Read(ref _seed);
next = current * SeedFactor;
} while (Interlocked.CompareExchange(ref _seed, next, current) != current);
return (int)next ^ Environment.TickCount;
}
}

Related

How to use a ref parameter in a thread if "Error CS1628: Cannot use in ref or out parameter inside an anonymous method, lambda or query expression"?

I am trying to write a tweening class, and in order to do so I have a static Tweener.TweenTo method. In it, we start a thread in order to not hold up external operations. The method looks like this:
public static void TweenTo<T>(ref ITweenable<T> obj, T target, double ms)
{
new System.Threading.Thread(() => {
System.Threading.Thread.Sleep(5000)
obj.DoStuff(5,5) //throws exception because obj is a ref parameter
}).Start()
}
I understand that using the ref parameter in the lambda means that it may be a dangling reference, but I need to be able to use it in case the user tries to pass a value type or struct to the method. I have tried using parameterized thread start, but that coerces things to an object, which I cannot use (unboxing etc.). I have also tried using a wrapper class that holds a pointer to it, but this runs in to complications later down the line.
I would like a way of using this ref parameter in the thread, and ideally preserving its lifetime inside it.
Any help is appreciated :D
Edit: Olivier's answer close to what I need, but MyClass would be a struct in some cases, and it will duplicate whenever it can. This means that it would lose the reference and give values from the wrong instance.
Edit 2: example struct
public struct MyStruct : ITweenable<T> {
int x;
int y;
public MyStruct(int X) {
this.x=X;
}
public void DoStuff(int newX, int newY) {
this.x=newX;
this.y=newY;
}
}
public interface ITweenable<T> {
void DoStuff(int newX, int newY);
}
Edit 3: I haven't tested this so when I have I will give it as an answer - have tested now, doesn't work:
public static void TweenTo<T>(ITweenable<T> obj, T target, double ms)
{
Func<ITweenable<T>> getTween = ()=>{return obj;}
new System.Threading.Thread(() => {
System.Threading.Thread.Sleep(5000)
getTween().DoStuff(5,5);
}).Start()
}
I'd suggest passing an Action<ITweenable<T>> to enable the assignment. Like this:
public static void TweenTo<T>(ITweenable<T> obj, Action<ITweenable<T>> update, T target, double ms)
{
new System.Threading.Thread(() =>
{
obj.DoStuff();
update(new Tweenable<T>());
}).Start()
}
Using an intermediate local var
Without considering the design and the reason for having the parameter by ref, nor any thread concurrency and interlocking management, just use an intermediate local var:
public static void TweenTo<T>(ref ITweenable<T> obj, T target, double ms)
{
var instance = obj;
new System.Threading.Thread(instance.DoStuff).Start();
}
Test
public interface ITweenable<T>
{
void DoStuff();
}
public class MyClass : ITweenable<int>
{
public void DoStuff()
{
Console.WriteLine("It works!");
Console.WriteLine("Press any key to exit the side thread.");
Console.ReadKey();
}
}
static private void Test()
{
var instance = (ITweenable<int>)new MyClass();
TweenTo(ref instance, 10, 20);
Console.WriteLine("Main thread ended.");
}
Output
Main thread ended.
It works!
Press any key to exit the side thread.
Remark for struct and code added in the question
It works the same, for the code and the case provided:
public interface ITweenable<T>
{
T X { get; }
T Y { get; }
void DoStuff(T newX, T newY);
}
public struct MyStruct : ITweenable<int>
{
public int X { get; private set; }
public int Y { get; private set; }
public void DoStuff(int newX, int newY)
{
Thread.Sleep(2000);
X = newX;
Y = newY;
Console.WriteLine("It works!");
}
}
public static void TweenTo<T>(ref ITweenable<T> obj, T target, double ms)
{
var instance = obj;
new System.Threading.Thread(() => instance.DoStuff((T)(object)10, (T)(object)10)).Start();
Console.WriteLine("Exiting TweenTo.");
}
Test
static private void Test()
{
var instance = (ITweenable<int>)new MyStruct();
Console.WriteLine("X is " + instance.X);
TweenTo(ref instance, 10, 20);
Console.WriteLine("Main thread ended.");
Console.WriteLine("Wait for the 'It Works' and press any key to continue main thread.");
Console.ReadKey();
Console.WriteLine("X is now " + instance.X);
Console.ReadKey();
}
Output
X is 0
Exiting TweenTo.
Main thread ended.
Wait for the 'It Works' and press any key to continue main thread.
It works!
X is now 10
Values by reference cannot be used across threads or in any deferred execution because .NET cannot enforce its memory management.
The struct in the ref lives on the stack of the calling function and can only be used when inside the scope of that function call.
The struct is a field in an other class and the reference is a pointer pointing to somewhere in the middle of the objects memory. The Garbage Collector cannot track these pointers and they are not allowed to live longer than the function call that created this reference. This function call has the original pointer to the object on its stack and with that the Garbage Collector can track the object.
So, in short, objects that need to be tweenable cannot be structs. The only solution is to make the class that contains this struct tweenable. Or if the tweenables are contained in an array implement a helper like this:
public class TweenableArray<T> : ITweenable<T>
{
private readonly ITweenable<T>[] _data;
public TweenableArray(ITweenable<T>[] data)
{
_data = data
}
void DoStuff(int newX, int newY)
{
for (var i = 0; i < _data.Length; i++)
_data[i].DoStuff(newX, newY)
}
}
Provided that newX and newY can be used for the whole array.

How to force all instances of Random generate same sequence of numbers in different runs?

I'm writing an application for testing an algorithm with random generated inputs. This involves several instances of Random class spread around the code. I need all these instances to generate same inputs in different runs to debug the algorithm when I find an unexpected result. This is the behavior of the apps created with Delphi, unless you manually call Randomize.
I know I can:
Provide constant seeds for all created instances.
Pass a unique instance, which is created with a constant seed, to all methods that need a random generator.
The reason I prefer not to use any of the above methods is that most of the functions that generate random data are kind of black box functions that are collected here and there on the Internet. Some of them even use several random generators for unknown reasons. I prefer not to mess with these functions unless I really have to.
So, are there any other ways to control all these instances together?
Here's a quick example of a class with two static members, one a "fixed RNG", while the other just a normal "RNG", that you can use from anywhere in your code:
int x = MyRandom.RNG.Next(1, 7);
int y = MyRandom.FixedRNG.Next(1, 7);
Code:
public class MyRandom
{
private static Random _fixedRandom = new Random(1234);
private static Random _random = new Random();
public static Random FixedRNG
{
get
{
return _fixedRandom;
}
}
public static Random RNG
{
get
{
return _random;
}
}
}
An alternative might be to include an IsRandom property that determines which one gets returned:
public class MyRandom
{
private static bool _isRandom = false;
private static Random _fixedRandom = new Random(1234);
private static Random _random = new Random();
public static bool IsRandom
{
get
{
return _isRandom;
}
set
{
_isRandom = value;
}
}
public static Random RNG
{
get
{
if (IsRandom)
return _random;
else
return _fixedRandom;
}
}
}
Thanks to #Idle_Mind for their suggestion. Here is a more Delphi-like version:
public static class GlobalRandom
{
private static int _randSeed = 0;
public static Random RNG { get; private set; } = new Random(_randSeed); // Made accessible for Random extensions
public static void Randomize() { RNG = new Random(); }
public static int RandSeed { get => _randSeed;
set { _randSeed = value; RNG = new Random(_randSeed); } }
public static int Next() => RNG.Next();
public static int Next(int minValue, int maxValue) => RNG.Next(minValue, maxValue);
public static int Next(int maxValue) => RNG.Next(maxValue);
public static void NextBytes(byte[] buffer) => RNG.NextBytes(buffer);
public static double NextDouble() => RNG.NextDouble();
}
Use it like:
Console.WriteLine($"Default seed (0): {GlobalRandom.Next()}");
GlobalRandom.Randomize();
Console.WriteLine($"Unknown seed: {GlobalRandom.Next()}");
GlobalRandom.RandSeed = 100;
Console.WriteLine($"Constant seed (100): {GlobalRandom.Next()}");
GlobalRandom.RandSeed = 0;
Console.WriteLine($"Back to default seed: {GlobalRandom.Next()}");
First Run:
Default seed (0): 1559595546
Unknown seed: 1837960504
Constant seed (100): 2080427802
Back to default seed: 1559595546
Second Run:
Default seed (0): 1559595546
Unknown seed: 54655523
Constant seed (100): 2080427802
Back to default seed: 1559595546

Rolling a dice with custom amount of faces

So i am creating a dice using a public class called die. this class has 2 constructors and 3 other methods. When i call class within the main program, it will not print the desired (random) result.
Firstly i am trying to print out a random number between 1-6 based on the default values. Once i figure this out, i would eventually like to specify a number of sides for and print out a number between 1 and this specific number.
/// Represents one die (singular of dice) with faces showing values between
/// 1 and the number of faces on the die.
public class Die
{
private int numFaces, faceValue;
public Die() => (numFaces, faceValue) = (6, 1);
public Die(int faces)
{
numFaces = faces;
if (numFaces < 3)
numFaces = 6;
faceValue = 1;
}
public void RollDie()
{
//for (int ctr = 0; ctr <= numFaces; ctr++)
var rnd = new Random();
for (int ctr = 1; ctr <= 20; ctr++)
faceValue = rnd.Next(1, numFaces + 1);
}
public int GetFaceValue() => faceValue;
public int GetNumFaces() => numFaces;
}
public class Program
{
public static void Main()
{
var myDie = new Die(1);
for (int i =0; i < 20; i++)
{
myDie.RollDie();
Console.WriteLine(myDie.GetFaceValue());
}
}
}
Since Random is time seeded when the parameterless constructor is used, this can have the very negative consequence of duplicating results.
Excerpt from the API documentation:
However, because the clock has finite resolution, using the
parameterless constructor to create different Random objects in close
succession creates random number generators that produce identical
sequences of random numbers.
...
On most Windows systems, Random objects created within 15 milliseconds of one another are likely to have identical seed values.
This is a safer approach in regards to getting random numbers when creating and rolling multiple dice:
public class Die
{
static int seed = Environment.TickCount;
static readonly ThreadLocal<Random> DieRandom = new ThreadLocal<Random>(()
=> new Random(Interlocked.Increment(ref seed)));
public int FaceCount { get; }
public int Value { get; private set; }
public Die() : this(6) // default to 6 faces
{
}
public Die(int faceCount)
{
if (faceCount < 3) // validate input
throw new ArgumentOutOfRangeException(nameof(faceCount));
this.FaceCount = faceCount;
}
public int Roll()
{
Value = DieRandom.Next(1, FaceCount + 1);
return Value;
}
}
Edit: updated the Random with thread safety as suggested here.

c# random numbers in abstract properties

How do I create an abstract property that can be a random number?
Parent.cs:
public abstract float ageInYears{get;}
Child.cs:
public override float ageInYears{
get{
return Random.Range(0, 10);
}
}
How do I ensure that Child.cs sets ageInYears to a random number, and that random number stays the same whenever accessed in the future?
private float? age;
public override float ageInYears{
get{
if(!age.HasValue) {
age = 10.0f * ((float) x.Next()) / ((float) int.MaxValue);
}
return age;
}
I use a method I call a Managed Entropy Source. Just a static class that creates a Random, then I call methods on MES, which being static, makes all random numbers come from the same 'stream', preventing the problem where 1000+ rng pulls can sometimes have just 2 values.
Also you can make nice wrappers, like CoinFlip() or Pick(list)
Helps when debugging random events, since you can swap out your MES implementation for a fake one that just reads from a file, or maybe inputbox's the number from the user ;)
An cryptographically seeded instance of Random is created per thread (inspired by this answer: https://stackoverflow.com/a/12952155/315689).
The backing property _ageInYears is initialized during the creation of each Child. Subsequent calls to the public ageInYears property will return the same value for a given instance of Child.
public class Child : Parent
{
[ThreadStatic]
private static Random _random;
private float _ageInYears;
public override float ageInYears { get { return _ageInYears; } }
public Child()
{
if (_random == null)
{
var cryptoResult = new byte[4];
new RNGCryptoServiceProvider().GetBytes(cryptoResult);
int seed = BitConverter.ToInt32(cryptoResult, 0);
_random = new Random(seed);
}
_ageInYears = (float)_random.NextDouble() * 10f;
}
}
https://dotnetfiddle.net/pmM5EC

Generic functions on Arrays in .NET

I often work with arrays of int/float and other things on a regular basis in C# since they are faster (maybe?) than List. Currently I've got dozens of functions implemented per type:
/// <summary>
/// Checks if the array contains the given value.
/// </summary>
public static bool contains(int[] values, int value) {
for (int s = 0, sl = values.Length; s < sl; s++) {
if (values[s] == value) {
return true;
}
}
return false;
}
/// <summary>
/// Checks if the array contains the given value.
/// </summary>
public static bool contains(float[] values, float value) {
for (int s = 0, sl = values.Length; s < sl; s++) {
if (values[s] == value) {
return true;
}
}
return false;
}
Is there a way to implement these in a generic way? Or is that only possible if I use List<T>?
The System.Array type has a dizzying array of static methods that can help you search, arrange, sort etc your arrays. You definitely do not need to roll your own. These static methods (like Find, FindAll) also accept generic arguments. Here's the list, dumped with the aid of PowerShell:
Name Definition
---- ----------
AsReadOnly static System.Collections....
BinarySearch static int BinarySearch(ar...
Clear static void Clear(array ar...
ConstrainedCopy static void ConstrainedCop...
ConvertAll static TOutput[] ConvertAl...
Copy static void Copy(array sou...
CreateInstance static array CreateInstanc...
Equals static bool Equals(System....
Exists static bool Exists[T](T[] ...
Find static T Find[T](T[] array...
FindAll static T[] FindAll[T](T[] ...
FindIndex static int FindIndex[T](T[...
FindLast static T FindLast[T](T[] a...
FindLastIndex static int FindLastIndex[T...
ForEach static void ForEach[T](T[]...
IndexOf static int IndexOf(array a...
LastIndexOf static int LastIndexOf(arr...
ReferenceEquals static bool ReferenceEqual...
Resize static void Resize[T]([ref...
Reverse static void Reverse(array ...
Sort static void Sort(array arr...
TrueForAll static bool TrueForAll[T](...
Thanks #Servy for your corrections :
/// <summary>
/// Checks if the array contains the given value.
/// </summary>
public static bool Contains<T>(T[] values, T value) {
for (int s = 0, sl = values.Length; s < sl; s++) {
if (object.Equals(values[s].value)) {
return true;
}
}
return false;
}
For this kind of things, you may also use Linq :
using System.Linq;
...
var myArray = new float[12];
...
if(myArray.Any(a => a == 2.4))

Categories

Resources