2013-06-05 101 views
1

我有一個靜態類中的靜態變量列表。從靜態類中選擇一個隨機靜態變量

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); 
+2

爲什麼不使用枚舉? – makc

+0

@makc:「Numbers」類來自第三方dll –

+0

@RameshDurai這並不妨礙您將所有靜態變量複製到您自己的數組中。 – Rotem

回答

5

使用反射:

創建整數Numbers的陣列作爲一個靜態屬性和在類Numbers其初始化爲值::

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

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

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

更好溶液

然後當得到一個隨機值:

int randomVariable = Numbers[rnd.Next(Numbers.Length)]; 
+0

+1,但不要忘記你_really_希望你的'隨機'在成員或靜態變量,而不是像這樣的局部變量。 – Rawling

3

您可以創建一個int數組,在上下數組索引之間生成一個隨機數,並使用它訪問數組索引。

否則,對於您的工作方法,必須使用反射,這會影響性能並且不是非常優雅。例如,獲取類中的所有PropertyInfos,使用它們創建和排列,獲取和隨機索引以及調用PropertyInfo值。

+0

我同意.... – Arun

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 

但總的來說,這是非常奇怪的靜態字段的用法,我會審查設計,如果它是一切OK。

+0

使用'Guid.NewGuid()'似乎有點沉重,爲什麼不使用'隨機'? – Dai

+0

使用反射比使用Guid更重,我認爲,所以使用Guid的時間更短:) – Giedrius

+2

Guids不適合隨機,不應該用於此目的。 http://stackoverflow.com/questions/467271/how-random-is-system-guid-newguid –

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)); 
2

您可以在課堂上使用reflection。請注意,如果您不想枚舉所有常量整數,則需要在其上枚舉要枚舉的標記。這將使用自定義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(); 
    } 
    } 
} 
+0

+1用於「過濾」和「自定義屬性」。 –

1

既然你知道類型,你不需要反思 - 這樣的東西就這麼簡單,應該沒有問題:

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(); 
+0

這個解決方案似乎沒問題。但問題是,我在班級Numbers中有將近100個變量。編寫開關盒會很困難。 –

+2

@RameshDurai你不是指「困難」 - 你的意思是「乏味和耗時」。 ;) –

+0

是!你是對的:) –