Only evaluate input sequence once in RandomOrDefault.
This ensures non-deterministic sequences cannot crash by returning an empty sequence on the second evaluation.
This commit is contained in:
@@ -136,19 +136,27 @@ namespace OpenRA
|
|||||||
|
|
||||||
public static T Random<T>(this IEnumerable<T> ts, MersenneTwister r)
|
public static T Random<T>(this IEnumerable<T> ts, MersenneTwister r)
|
||||||
{
|
{
|
||||||
var xs = ts as ICollection<T>;
|
return Random(ts, r, true);
|
||||||
if (xs != null)
|
|
||||||
return xs.ElementAt(r.Next(xs.Count));
|
|
||||||
var ys = ts.ToList();
|
|
||||||
return ys[r.Next(ys.Count)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T RandomOrDefault<T>(this IEnumerable<T> ts, MersenneTwister r)
|
public static T RandomOrDefault<T>(this IEnumerable<T> ts, MersenneTwister r)
|
||||||
{
|
{
|
||||||
if (!ts.Any())
|
return Random(ts, r, false);
|
||||||
return default(T);
|
}
|
||||||
|
|
||||||
return ts.Random(r);
|
static T Random<T>(IEnumerable<T> ts, MersenneTwister r, bool throws)
|
||||||
|
{
|
||||||
|
var xs = ts as ICollection<T>;
|
||||||
|
xs = xs ?? ts.ToList();
|
||||||
|
if (xs.Count == 0)
|
||||||
|
{
|
||||||
|
if (throws)
|
||||||
|
throw new ArgumentException("Collection must not be empty.", "ts");
|
||||||
|
else
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return xs.ElementAt(r.Next(xs.Count));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Product(this IEnumerable<float> xs)
|
public static float Product(this IEnumerable<float> xs)
|
||||||
|
|||||||
Reference in New Issue
Block a user