I thought it might be worth sharing something I found as (a) it might be helpful and (b) you might spot a problem with the method.
Essentially in our overridden variants of GetAlllFeaturesCore and GetFeaturesInBoundingBoxCore we added some code to handle excluded IDs and this made a significant performance improvement when excluding larger numbers of IDs. If we didn’t do this they were still excluded but it took much longer to draw the map.
CODE: SNIPPIT
` if (this.FeatureIdsToExclude.Count > 0) {
List<string> wanted = features.Select(
x => x.Id).ToList().Except(this.FeatureIdsToExclude).ToList();
return new Collection<Feature>(features.Where(x => wanted.Contains(x.Id)).ToList());
}`
A quick extra note: The above was broadly correct but not totally so, as it worked well when the number to exclude was a large proportion of the total number but very inefficiently when reversed. I did some rework to create a custom Comparer for the Exclude that also simplified it a bit.
Thanks for your suggestion! I logged it down and we will apply your suggestion to the future versions.
Also, I think we can make a couple improvements upon your code, please have a look see if it make sense:
if (this.FeatureIdsToExclude.Count > 0)
{
// avoid using ToList(), to
// 1, avoid creating Lists to save some memory
// 2, delay the enumerating to the foreach statement where it is really needed.
var wantedEnumerable = features.Select(x => x.Id).Except(this.FeatureIdsToExclude);
// use HashSet which has O(1) for Contains, instead of List<string) which has O(n) for Contains
var wanted = new HashSet<string>();
foreach (var feature in wantedEnumerable)
wanted.Add(feature);
return new Collection<Feature>(features.Where(x => wanted.Contains(x.Id)).ToList());
}
Also, just let you know the latest product release v13.2.* is now available on nuget. Please upgrade to that version if you are on beta.
Thanks Ben, that was very helpful. Prior to that I had done some rework and ended up with something a bit different again:
The bit to process the list/collection is split out and looks like this:
// Use FeatureIDsToExclude to strip out unwanted features from the return
private Collection<Feature> AllowForExclusions(Collection<Feature> features)
{
var filteredApps = features.Except(FeatureIdsToExclude.Select(x => new Feature { Id = x }), new FeatureComparer());
return new Collection<Feature>(filteredApps.ToList());
}
And then had this as the comparer:
/// <summary>
/// Class to manage comparing Fetaures on the bases that if the IDs are equal than they are the same feature.
/// </summary>
/// <remarks>
/// Will be used by LINQ .Except operator to manage excluding unwanted features based on a list of IDs
/// </remarks>
class FeatureComparer : IEqualityComparer<Feature>
{
/// <summary>
/// Straight forward string compare on IDs
/// </summary>
/// <param name="f1"></param>
/// <param name="f2"></param>
/// <returns></returns>
public bool Equals(Feature f1, Feature f2)
{
return string.Equals(f1.Id, f2.Id);
}
/// <summary>
/// Returns hash code of just the ID, needed by LINQ .Exclude
/// </summary>
/// <param name="f"></param>
/// <returns></returns>
public int GetHashCode(Feature f)
{
return f.Id.GetHashCode();
} }