2

我有一个静态类中的静态变量列表。

namespace Test
{
  public static class Numbers
  {
    public static readonly int One = 1;
    public static readonly int Five = 5;
    public static readonly int Ten = 10;
    public static readonly int Eleven = 11;
    public static readonly int Fifteen= 15;
  }
}

我想在课堂上随机选择一个变量。我怎样才能做到这一点?

int randomVariable = SomeFunction(Numbers);
4

6 回答 6

6

使用反射:

FieldInfo[] fields= typeof(Numbers).GetFields(
   BindingFlags.Public | BindingFlags.Static);

var rnd = new Random();
int randomVariable = (int) fields[rnd.Next(fields.Length)].GetValue(null);

没有反射的更好的解决方案:

创建一个整数数组Numbers作为静态属性并将其初始化为类中的值Numbers

Numbers = fields.Select(f => (int)f.GetValue()).ToArray(); //int[]

然后在获取随机值时:

int randomVariable = Numbers[rnd.Next(Numbers.Length)];
于 2013-06-05T08:06:04.370 回答
4
  var fields = typeof(Numbers).GetFields(BindingFlags.Static | BindingFlags.Public);
  var value = fields
         .OrderBy(x => Guid.NewGuid()) // order by random
         .First() // take first field
         .GetValue(null); // get it's value

但总的来说,静态字段的使用非常奇怪,如果一切正常,我会审查设计。

于 2013-06-05T08:06:01.887 回答
3

您可以创建一个 int 数组,在上下数组索引之间生成一个随机数,并用它访问数组索引。

否则,对于您的工作方法,必须使用反射,这会降低性能并且不是很优雅。例如,获取类中的所有 PropertyInfo,用它们创建和排列,获取和随机索引并调用 PropertyInfo 值.

于 2013-06-05T08:05:07.307 回答
2

您可以通过对类使用反射来做到这一点。请注意,如果您不想枚举所有 const int,则需要在它们上添加要枚举的标记。这将使用自定义Attributes来完成。

namespace ConsoleApplication4
{
  using System;
  using System.Collections.Generic;
  using System.Linq;

  public class Holder
  {
    public const int Number1 = 7;

    public const int Number2 = 17;

    public const int Number3 = 42;

    public static IEnumerable<int> AllNumbers()
    {
      return
        typeof(Holder).GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
                      .Where(p => p.FieldType == typeof(int))
                      .Select(p => (int)p.GetValue(null));
    }

    public static int RandomNumber(Random r)
    {
      var possibleNumbers = AllNumbers().ToList();

      var draw = r.Next(possibleNumbers.Count);

      return possibleNumbers[draw];
    }
  }

  public class Program
  {
    public static void Main()
    {
      var r = new Random();

      for (int i = 0; i < 10; i++)
      {
        Console.WriteLine(Holder.RandomNumber(r));
      }

      Console.WriteLine("Done");
      Console.ReadLine();
    }
  }
}
于 2013-06-05T08:10:47.030 回答
2

由于您知道类型,因此不需要反射 - 所以像这样简单的事情应该没问题:

public sealed class NumbersRandomizer
{
    readonly Random rng = new Random();

    public int RandomValue()
    {
        switch (rng.Next(5))
        {
            case 0: return Numbers.One;
            case 1: return Numbers.Five;
            case 2: return Numbers.Ten;
            case 3: return Numbers.Eleven;
            case 4: return Numbers.Fifteen;
        }
    }
}

你会像这样使用它:

var randomizer = new NumbersRandomizer();
int value = randomizer.RandomValue();
于 2013-06-05T08:19:21.727 回答
0

如果您使用Enum.

public enum Numbers {
    One = 1,
    Five = 5,
    Ten = 10,
    Eleven = 11
    Fifteen = 15
}

然后随机选择枚举。

var numbers = Enum.GetValues(typeof(Numbers));

Number randomNumber = (Number)numbers.GetValue(new Random().Next(numbers.Length));
于 2013-06-05T08:08:25.860 回答