All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project (will try to) adhere to Semantic Versioning.
- Added
FilterNode.Combine
extension method
Some major changes took place in this release to simplify things that were just way too complicated. Previously, leaf nodes were actually filters, i.e. they inherited from ILeafFilterNode
and also implemented the filter logic.
E.g.
public class CharFilter : LeafFilterNode<CharFilter>, IRealisableLeafFilterNode<string>, IEquatable<IFilterNode>
...
public bool IsMatch(string item) => ...
In this release, leaf nodes don't have an inheritance relationship with filter implementations; there is now a composition relationship. That is, leaf node "has" a filter, not "is" a filter.
This means we could safely remove all the generic constraints which were so confusing and just not working well in a language (c#) that doesn't support higher-kinded types.
Refer to the README.md for updated example usage. For an example on how to migrate, look at what changed in the tests in the commit tagged version/4.0.0, e.g. CharFilter.cs.
- Added
Filter<T>
class which provides a convenient base class for implementing realisable filters - Added
IEquatable
toIFilterNode
- Added
Collapse
method toIFilterNode
- Added
IsCollapsed
bool toIFilterNode
to indicate whether or not a filter has already been collapsed.- Calling
Collapse()
when this istrue
will have no effect and simply return the already collapsed node.
- Calling
- Added
Sort
method toIFilterNode<TFilter>
which recursively sorts nodes according to the suppliedIComparer<IFilterNode<TFilter>>
.- There is also a default comparer,
FilterNodeComparer
. The order of nodes of different types is leaf, inverted, combination. - When sorting adjacent leaf nodes, it will use the supplier
IComparer<TFilter>
, orComparer<TFilter>.Default
if none is specified (which meansTFilter
would need to implementIComparable<TFilter>
, or a run-time exception would be thrown when callingSort()
) - When sorting adjacent combination nodes, it will use lexicographical sequence order
- When sorting adjacent inverted nodes, it will sort by the inner nodes to be inverted
- There is also a default comparer,
- Renamed some classes/interfaces:
Before After CombinationFilter
CombinationFilterNode
ICombinationFilter
ICombinationFilterNode
InvertedFilter
InvertedFilterNode
IInvertedFilter
IInvertedFilterNode
IRealisableLeafFilterNode
IFilter
- Changed
LeafFilterNode
tosealed
and addedFilter
property - Changed storage in
CombinationFilterNode
to always be an array, and removedpreserveOrder
from the constructor.- This means nodes are always ordered, and this will affect equality.
- There are two ways to resolve this:
- Call
Sort()
on nodes before callingEquals()
- Use
IsEquivalentTo
instead ofEquals()
, which will internally use aSetEquals
operation
- Call
- Changed the type of the leaf parameter of
Aggregate
andMatch
fromFunc<TFilter, TResult>
toFunc<ILeafFilterNode<TFilter>, TResult>
- Moved methods
IsTrue()
andIsFalse()
fromIFilterNode<TFilter>
toIFilterNode
: - Moved extension method
IsEquivalentTo
into interfaceIFilterNode
- Removed
InternalFilterNode
andIInternalFilterNode
- Removed convoluted/confusing generic constraints
- Use arrays in some functions like
Aggregate
so that we can benefit from usingfor
loops without needing to allocate iterators or lambdas to combine the results - Renamed
ICombinationFilterNode
to simplyICombinationFilter
- Removed
OrderedCombinationFilter
and added new parameterPreserveOrder
to constructor ofCombinationFilter
.
- [3.0.2] Collapsing a
CombinationFilter
should cause any innerCombinationFilter
s of the sameOperator
to be flattened onto the outerCombinationFilter
- [3.0.3] Collapsing a
CombinationFilter
should cause any innerCombinationFilter
s of the oppositeOperator
to be absorbed if the inner filters contains one of the outer filters