Your code functions correctly. The only problem arises from the fact
that the Random object does not generate truly random numbers (It's a
pseudo-random generator). However, the Random class allows you to
generate sufficiently random sequences for this purpose by providing a
unique seed value.
There are many ways to generate this unique seed. In the below code, I
demonstrate three of them :
1. Use a value that depends on the current time. However, since your
loop runs so fast, the system time does not change significantly
enough for seed values to change. Therefore, we must apply a trick...
we must simulate a delay so that the time changes. I do this by
setting the current thread to sleep for a very minimal time (so as not
to affect program performance significantly). This is demonstrated by
the function "SleepingWithRandom" in the code sample.
2. Use the loop counter as the seed value, since it is guaranteed to
be unique for each iteration. This is demonstrated by the function
"LoopingRandom" in the code sample.
3. Use a seed value derived from the loop value. If it is even, apply
a bitwise complement of the current time (in ticks), else not. This
would greatly increase the probability that the seed value generated
is unique even for the same time. This is demonstrated by the function
"ComplementingRandom" in the code sample.
The code: (Syntax highlighted version available at: <http://
dotnetdevelopment.pastebin.com/m5236e4af>)
---
using System;
using System.Threading;
interface IFoo
{
void foo(int a, int b);
}
class Factory : IFoo
{
private enum Operation
{
add = 1,
subtract = 2,
multiply = 3,
divide = 4,
}
private int _a, _b;
private int randomSeed = 0;
public virtual void foo(int a, int b)
{
this._a = a;
this._b = b;
Random rand = new Random(randomSeed);
Operation op = (Operation)rand.Next(1, 5);
switch (op)
{
case Operation.add:
plus();
break;
case Operation.subtract:
minus();
break;
case Operation.multiply:
multiplier();
break;
case Operation.divide:
dividor();
break;
}
//if (rand.Next(4) % 4 == 0)
// plus();
//else if (rand.Next() % 4 == 1)
// minus();
//else if (rand.Next() % 4 == 2)
// dividor();
//else multiplier();
}
public void plus()
{
Console.WriteLine("{0}+{1}={2}", _a, _b, _a + _b);
}
public void minus()
{
Console.WriteLine("{0}-{1}={2}", _a, _b, _a - _b);
}
public void dividor()
{
Console.WriteLine("{0}/{1}={2}", _a, _b, _a / _b);
}
public void multiplier()
{
Console.WriteLine("{0}*{1}={2}", _a, _b, _a * _b);
}
public int RandomSeed
{
set { randomSeed = value; }
}
}
class MainClass
{
static void Main(string[] args)
{
IFoo[] df = new IFoo[10];
for (int i = 0; i < 10; i++)
{
Factory f = new Factory();
// Uncomment only one of the below 3 approaches at a time:
//SleepingWithRandom(ref f, i);
LoopingRandom(ref f, i);
//ComplementingRandom(ref f, i);
df[i] = f;
}
}
private static void SleepingWithRandom(ref Factory f, int i)
{
// Generate a seed from the current time and set the seed value of
the Random to be created.
f.RandomSeed = unchecked((int)(DateTime.Now.Ticks));
f.foo(i + 1, i + 1);
// Initiate a delay so as to increase randomness.
Thread.Sleep(20);
}
private static void LoopingRandom(ref Factory f, int i)
{
// Generate a different seed using the loop variable itself.
f.RandomSeed = i;
f.foo(i + 1, i + 1);
}
private static void ComplementingRandom(ref Factory f, int i)
{
// Generate a different seed based on whether the loop variable is
even or odd.
if (i % 2 == 0)
f.RandomSeed = ~unchecked((int)(DateTime.Now.Ticks));
else
f.RandomSeed = unchecked((int)(DateTime.Now.Ticks));
f.foo(i + 1, i + 1);
}
}
---
I think the "LoopingRandom" method should be sufficient for your
purposes. You can therefore remove the extraneous code which is only
for illustration of all three approaches to the problem.
Note that I commented your if-else constructs and used an Enum
variable instead. I think it's more "intuitive", this way !