c# forms: where do i place my random number generator?
I was trying to use a random number generator in a windows forms app, but I'm having trouble figuring out where to put it. I'm being told "place it in the form constructor" but I don't think we're talking the same language. Here's the code im trying to find a home for:
Random rnd = new Random();
int guessMe = rnd.Next(0,100);
But whenever I try to place it outside of the click even method, it says:
A field initializer cannot reference the non-static field, method, or property 'LAB6B.Form1.r'
So i'm assuming that means what it sounds like; it has to be inside of a static method. But the form constructor doesn't seem to have any static methods either. Can someone toss me a bone?
Here is the code from the the Form1.cs. Im reading some other tutorial online right now that is saying to do the random number generator in the Form1_Load event, but I'm getting a context/scope error from the button click event.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace LAB6B
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Random rnd = new Random();
int guessMe = rnd.Next(0, 100);
}
private void btnEvaluate_Click(object sender, EventArgs e)
{
int totGuesses = 0, myGuess;
if (txtGuess.Text != "")
{
my开发者_Go百科Guess = int.Parse(txtGuess.Text);
totGuesses++;
if (myGuess < guessMe)
{
btnEvaluate.Visible = false;
lblResult.Text = "Too Low!!";
lblResult.Visible = true;
BackColor = Color.SeaGreen;
}
}
}
}
}
If you've been given that advice, someone is probably suggesting that you declare an instance variable, but initialize it in your constructor. For example:
public class Foo
{
private readonly Random rnd;
public Foo()
{
rnd = new Random();
// Other construction code
}
}
Then you can use rnd
anywhere in your class.
This is actually mostly equivalent to:
public class Foo
{
private readonly Random rnd = new Random();
public Foo()
{
// Other construction code
}
}
... which I mostly prefer, as it shows that the initialization of rnd
has nothing to do with any constructor parameters.
As it seems that part of your difficulty is with the guessMe
variable, here's a more complete version:
public class Foo
{
private readonly Random rnd = new Random();
private int guessMe;
public Foo()
{
guessMe = rng.Next(0, 100);
}
}
This is assuming you need guessMe
to be an instance variable so you can refer to it throughout the class. On the other hand, perhaps you don't need the Random
variable to be an instance variable - if you're only generating one random number, it would be better as:
public class Foo
{
private readonly int guessMe;
public Foo()
{
Random rnd = new Random();
guessMe = rnd.Next(0, 100);
}
}
However, personally I wouldn't use either of these approaches. I would use a technique which creates a single instance of Random
per thread, to avoid both the perils of Random
being non-thread-safe, and the perils of creating two instances of Random
very close to each other in time, and ending up with the same seeds.
I've written about this reasonably extensively in an article on my site, including this class:
using System;
using System.Threading;
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper =
new ThreadLocal<Random>(() =>
new Random(Interlocked.Increment(ref seed))
);
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}
You can either use RandomProvider
directly (calling GetThreadRandom
every time you need to generate a random number) or you can pass RandomProvider.GetThreadRandom
into your class as a constructor argument for a parameter of type Func<Random>
- i.e. inject a dependency of "I want to be able to get an instance of Random
at any time".
精彩评论