我有一个具有多个布尔(和整数)属性的对象。我想创建一个具有许多不同属性的对象集合,以便有一个用于测试的良好数据集。
例如
public class A
{
public int value {get; set;} //want to try beetween 0 and 5
public bool foo {get; set;}
public bool bar {get; set;}
public bool boo {get; set;}
}
对于这个例子,我喜欢有一个6 * 2 * 2 = 24 elementw的列表,value
= 0/1/2/3/4/5, foo
= true / false ,bar
= true / false,但boo
始终为false。
我可以使用24行代码来做到这一点。但它是很多,如果我再增加一个布尔,它的行数就会翻倍。
我可能每个属性使用一个循环,但我不认为这是一个有太多嵌套循环的好方法。我也可以通过反思来做到这一点,但我认为这是太多的工作,不是吗?
我认为还有另一种方法可以做得更好,但我找不到它。
答案 0 :(得分:3)
这个基于循环的旧方法有什么问题?
var boolVals = new[] { true, false };
var intVals = new[] { 0, 1, 2, 3, 4, 5 };
var myList = new List<A>();
foreach(var foo in boolVals) {
foreach(var value in intVals) {
foreach(var bar in boolVals) {
foreach (var boo in boolVals) {
myList.Add(new A { value = value, foo = foo, bar = bar, boo = boo });
}
}
}
}
您必须为添加的每个属性添加新的嵌套,并循环此属性可能具有的相应值集。
这个appraoch在几行简单易读的代码中填写了你的价值观的所有可能的排列。
当然看起来有点难看。但它只增加一个嵌套在每个添加的属性上。
答案 1 :(得分:1)
由于您没有明确要求全置换解决方案,我建议随机进行。你可以使用构造函数......
public class A
{
public int value {get; set;} //want to try beetween 0 and 5
public bool foo {get; set;}
public bool bar {get; set;}
public bool boo {get; set;}
public A()
{
// initialize value, foo, bar, boo with desired default / random here
}
}
var myList = new List<A>();
for (int i=0; i<=24; i++) myLyst.add(new A());
这对我来说似乎非常易读和可维护。您还可以将参数传递给新的A(),并在需要时使用它来计算第n个排列,但我想这超出了问题的范围。
答案 2 :(得分:0)
您可以使用反射和数据结构来跟踪每个属性的值(通过等效索引)
这会自动考虑类中的所有属性,只需添加到ValuesFor
字典
using System;
using System.Collections.Generic;
using System.Reflection;
public class Program
{
private static Dictionary<string, object[]> ValuesFor = new Dictionary<string, object[]>()
{
{ typeof(int).ToString(), new object[] { 0, 1, 2, 3, 4, 5 } },
{ typeof(bool).ToString(), new object[] { true, false } }
};
public static void Main()
{
var properties = typeof(A).GetProperties(BindingFlags.Instance | BindingFlags.Public);
int[] valueIndices = new int[properties.Length];
do
{
createObject(properties, valueIndices);
} while (setNext(properties, valueIndices));
Console.ReadKey();
}
/// <summary>
/// This updates the valueIndex array to the next value
/// </summary>
/// <returns>returns true if the valueIndex array has been updated</returns>
public static bool setNext(PropertyInfo[] properties, int[] valueIndices)
{
for (var i = 0; i < properties.Length; i++)
{
if (valueIndices[i] < ValuesFor[properties[i].PropertyType.ToString()].Length - 1) {
valueIndices[i]++;
for (var j = 0; j < i; j++)
valueIndices[j] = 0;
return true;
}
}
return false;
}
/// <summary>
/// Creates the object
/// </summary>
public static void createObject(PropertyInfo[] properties, int[] valueIndices)
{
var a = new A();
for (var i = 0; i < properties.Length; i++)
{
properties[i].SetValue(a, ValuesFor[properties[i].PropertyType.ToString()][valueIndices[i]]);
}
print(a, properties);
}
public static void print(object a, PropertyInfo[] properties)
{
Console.Write("Created : ");
for (var i = 0; i < properties.Length; i++)
Console.Write(properties[i].Name + "=" + properties[i].GetValue(a) + " ");
Console.Write("\n");
}
public class A
{
public int value { get; set; }
public bool foo { get; set; }
public bool bar { get; set; }
public bool boo { get; set; }
}
}
目前createObject
,只需创建对象并调用print
即可打印出对象。相反,您可以将其添加到集合中并使用它运行测试(或直接将测试替换为print
)