在软件开发过程中,经常需要一些测试数据来验证程序的功能。虽然在开发阶段,数据本身可能还不存在,但为了测试目的,仍然需要一些数据。当然,可以选择手动添加一些虚拟数据,但真正的开发者倾向于将这项工作交给计算机。因此,数据生成成为了一个任务。
如果谈论的是C#项目,数据生成意味着使用System.Random类,这是合适的,但不幸的是它缺乏一些有用的特性。尝试稍微改善这种情况,并编写了一些扩展方法,这些方法可能会派上用场。
下载扩展方法库:
- 12.7 KB
除了库本身,源代码还包含一个带有注释的工作示例。以下是一些[编辑过的]代码片段:
有一个NextDate方法,它像Random类的Next方法一样使用,但它返回DateTime对象而不是整数:
Random _random = new Random();
// 生日是1800年1月1日至25年前的日期之间的日期
DateTime birthFrom = new DateTime(1800, 1, 1);
DateTime birthTo = DateTime.Now.AddYears(-25);
DateTime birthDate = _random.NextDate(birthFrom, birthTo);
范围限制可以省略。请注意,DateTime变量的时间部分在这里被清零了;但还有一个NextDateTime方法。还有一个NextLong方法,它们都是基于这些方法的。
是的,使用Random类的Next方法从列表/数组中选择一个随机项并不困难,但以下代码更清晰一些:
Random _random = new Random();
string[] _lastNames = {
"Johnson",
"King",
"Verne",
"Hawk",
"Sterling",
"Stout",
"Webster",
"Knight",
"Aston",
"Anderson"
};
string lastName = _random.NextItem(_lastNames);
再次,这是可以通过标准方法实现的,但以下代码更短且相当清晰。
Random _random = new Random();
string[] _firstNames = {
"John",
"Rex",
"Andrew",
"Jonathan",
"Stephen",
"Frederick",
"Louis",
"Matthew"
};
string middleName = null;
// ...
// 1/3的人有中间名
if (_random.HitBullsEye(3)) {
// 在3/10的情况下,中间名只是一个字母(像Jerome K. Jerome)
middleName = _random.IsTrueWithProbability(0.3)
? $"{(char)('A' + _random.Next(0, 26))}."
: _random.NextItem(_firstNames);
}
请注意,HitBullsEye方法实际上是在射击目标上投掷飞镖(在这种情况下,由3个圆圈组成)并且只有在击中目标的靶心时才返回true。
但是,如果喜欢,也可以像这样投掷虚拟骰子:
// 1/2男性,1/2女性
Person.PersonSex sex = _random.ThrowDiceToHit(2, 2) ? Person.PersonSex.Male : Person.PersonSex.Female;
// (在ThrowDiceToHit方法中,第一个参数是骰子的面数,第二个参数是最低“获胜”值。因此,ThrowDiceToHit(6, 3)只有在骰子的上表面显示数字从3到6时才返回true,即在2/3的情况下。)
此外,可以将概率检查与选择列表项结合起来:
// 女性可能有婚前姓氏...
if (sex == Person.PersonSex.Female) {
// ...在7/10的情况下
maidenName = _random.NextItemOrDefault(_lastNames, 0.7);
}