From b66db23adf79046e390e1222596bcbe468f6a9c4 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sun, 22 Mar 2015 21:56:39 +0000 Subject: [PATCH] Only evaluate input sequence once in RandomOrDefault. This ensures non-deterministic sequences cannot crash by returning an empty sequence on the second evaluation. --- OpenRA.Game/Exts.cs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index 07021dc184..b5e3a6c9de 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -136,19 +136,27 @@ namespace OpenRA public static T Random(this IEnumerable ts, MersenneTwister r) { - var xs = ts as ICollection; - 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(this IEnumerable ts, MersenneTwister r) { - if (!ts.Any()) - return default(T); + return Random(ts, r, false); + } - return ts.Random(r); + static T Random(IEnumerable ts, MersenneTwister r, bool throws) + { + var xs = ts as ICollection; + 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 xs)