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:
RoosterDragon
2015-03-22 21:56:39 +00:00
parent 5ac648600d
commit b66db23adf

View File

@@ -136,19 +136,27 @@ namespace OpenRA
public static T Random<T>(this IEnumerable<T> ts, MersenneTwister r)
{
var xs = ts as ICollection<T>;
if (xs != null)
return xs.ElementAt(r.Next(xs.Count));
var ys = ts.ToList();
return ys[r.Next(ys.Count)];
return Random(ts, r, true);
}
public static T RandomOrDefault<T>(this IEnumerable<T> ts, MersenneTwister r)
{
if (!ts.Any())
return default(T);
return Random(ts, r, false);
}
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)