-1

I have a class filtercollection which holds a collection of Filters:

class TransactionTypeFilterCollection
{
    public CategoryNode FilterCollection { get; private set; }
    public TransactionTypeFilter[] Filters { get; private set; }
    public void AddFilter(string field, FilterOperator filterOperator, string value)
    {
        TransactionTypeFilter newFilter = new TransactionTypeFilter(
            filterCollection: this.FilterCollection,
            name: this.FilterCollection.Name + "_Filter_" + this.Filters.Length,
            field: field,
            filterOperator: filterOperator,
            value: value
        );
        TransactionTypeFilter[] newFilterCollection = new TransactionTypeFilter[this.Filters.Length+1];
        Array.Copy(this.Filters, 0, newFilterCollection,0, this.Filters.Length);
        newFilterCollection[this.Filters.Length] = newFilter;
        this.Filters = newFilterCollection;
    }
}

Specifically I am not using a List for elements cannot easily be added/removed from outside without accessing the proper function of the Filter Collection. Also for Performance reasons.

This code to extend the array feels somewhat cumbersome to me and does not "feel" right:

TransactionTypeFilter[] newFilterCollection = new TransactionTypeFilter[this.Filters.Length+1];
Array.Copy(this.Filters, 0, newFilterCollection,0, this.Filters.Length);
newFilterCollection[this.Filters.Length] = newFilter;
this.Filters = newFilterCollection;

I normally would do something like the following:

List<TransactionTypeFilter> newFilterCollection = this.Filters.ToList();
newFilterCollection.Add(newFilter);
this.Filters = newFilterCollection.ToArray();

But benchmarking showed that array.Copy is faster by a factor of 3~ and the result of method 2 gets worse the more elements I want to add.

Even with a plane List where I add elements, method 1 was faster.

Is there a better way to expand the array?

I found an answer in Is it possible to extend arrays in C#? but when trying Array.Resize in my class, I receive the compiler error: A property or Indexer may not be passed as out or ref parameter.

julian bechtold
  • 1,875
  • 2
  • 19
  • 49
  • 1
    Looks like a micro-optimization to me. How many elements are you storing in that arrays at worst? – Steve Jan 08 '22 at 22:26
  • By the way, `List` have a Capacity property or a constructor parameter that allows you to give the approximate number of elements to have in the list without resizing. Did you benchmark with this option? – Steve Jan 08 '22 at 22:29
  • You don't want to use `List<>` for performance reasons, so you've found a more performant solution but it doesn't "'feel' right", whatever that may mean. So what do you want? You can't have it both ways. `Array.Resize()` really would be the way to go, although you may find having to copy `this.Filters` into a temporary variable so you can pass it by `ref`erence to be just as "cumbersome" as the `Array.Copy()` approach. – Lance U. Matthews Jan 09 '22 at 00:31
  • 1
    I’m voting to close this question because it belongs on https://codereview.stackexchange.com/ – Ian Mercer Jan 09 '22 at 00:31

1 Answers1

1

Are you passing in the reference parameter correctly? The error indicates that you are trying to pass in a property. Properties are not variables and therefore cannot be passed as out parameters. This might work for your usages

private static Array ResizeArray(Array arr, int[] newSizes)
{
   var temp = Array.CreateInstance(arr.GetType().GetElementType(), newSizes);
   int length = arr.Length <= temp.Length ? arr.Length : temp.Length;
   Array.ConstrainedCopy(arr, 0, temp, 0, length);
   return temp;
}
Jacob
  • 371
  • 2
  • 18