public void TypeSlimEqualityComparer_EqualsGeneric()
        {
            var genericArguments = new List <TypeSlim> {
                SlimType, SlimType
            }.AsReadOnly();
            var definition1 = TypeSlim.GenericDefinition(new AssemblySlim("Foo"), "Bar");
            var definition2 = TypeSlim.GenericDefinition(new AssemblySlim("Bar"), "Foo");

            var equal = new[]
            {
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Generic(definition1, genericArguments), TypeSlim.Generic(definition1, genericArguments)),
            };

            var inequal = new[]
            {
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Generic(definition1, genericArguments), TypeSlim.Generic(definition2, genericArguments)),
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Generic(definition1, genericArguments), TypeSlim.Generic(definition1, genericArguments.Take(1).ToReadOnly())),
            };

            AssertAllEqual(equal);
            AssertAllNotEqual(inequal);
        }
        public void TypeSlimEqualityComparer_EqualsSimple()
        {
            var equal = new[]
            {
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(assembly: null, "Foo"), TypeSlim.Simple(assembly: null, "Foo")),
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(new AssemblySlim("Foo"), "Foo"), TypeSlim.Simple(new AssemblySlim("Foo"), "Foo")),
            };

            var inequal = new[]
            {
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(assembly: null, "Foo"), TypeSlim.Simple(assembly: null, "Bar")),
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(new AssemblySlim("Bar"), "Foo"), TypeSlim.Simple(new AssemblySlim("Bar"), "Bar")),
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(new AssemblySlim("Foo"), "Bar"), TypeSlim.Simple(new AssemblySlim("Bar"), "Bar")),
                new KeyValuePair <TypeSlim, TypeSlim>
                    (TypeSlim.Simple(new AssemblySlim("Foo"), "Bar"), TypeSlim.Simple(new AssemblySlim("Bar"), "Foo")),
            };

            AssertAllEqual(equal);
            AssertAllNotEqual(inequal);
        }
 internal ConditionalExpressionSlim(ExpressionSlim test, ExpressionSlim ifTrue, ExpressionSlim ifFalse, TypeSlim type)
 {
     Test    = test;
     IfTrue  = ifTrue;
     IfFalse = ifFalse;
     Type    = type;
 }
Exemplo n.º 4
0
 internal CatchBlockSlim(TypeSlim test, ParameterExpressionSlim variable, ExpressionSlim body, ExpressionSlim filter)
 {
     Test     = test;
     Variable = variable;
     Body     = body;
     Filter   = filter;
 }
Exemplo n.º 5
0
 internal GotoExpressionSlim(GotoExpressionKind kind, LabelTargetSlim target, ExpressionSlim value, TypeSlim type)
 {
     Kind   = kind;
     Value  = value;
     Target = target;
     Type   = type;
 }
Exemplo n.º 6
0
        public override TypeSlim ToType(DeserializationDomain domain, TypeSlim[] genericArguments)
        {
            if (_type == null)
            {
                var def = domain.GetType(_genericTypeDefinition).ToType(domain, genericArguments);
                GenericDefinitionTypeSlim genDef;

                switch (def.Kind)
                {
                case TypeSlimKind.Simple:
                    var simple = (SimpleTypeSlim)def;
                    genDef = TypeSlim.GenericDefinition(simple.Assembly, simple.Name);
                    break;

                default:
                    throw new InvalidOperationException("Expected either simple type slim discriminator for generic definition type.");
                }

                var n        = _genericTypeArguments.Length;
                var argsList = new TypeSlim[n];

                for (var i = 0; i < n; i++)
                {
                    var arg     = _genericTypeArguments[i];
                    var argType = domain.GetType(arg).ToType(domain, genericArguments);
                    argsList[i] = argType;
                }

                var args = new TrueReadOnlyCollection <TypeSlim>(/* transfer ownership */ argsList);
                _type = TypeSlim.Generic(genDef, args);
            }

            return(_type);
        }
Exemplo n.º 7
0
        public void MemberInfoSlimEqualityComparer_Method_Simple()
        {
            var tq = new TypeSlimEqualityComparer();
            var eq = new MemberInfoSlimEqualityComparer(tq);

            var asm = new AssemblySlim("foo");

            var tp1 = TypeSlim.Simple(asm, "bar");

            var i4 = typeof(int).ToTypeSlim();
            var i8 = typeof(long).ToTypeSlim();

            var args0 = new List <TypeSlim> {
                i4, i8
            }.AsReadOnly();
            var args1 = new List <TypeSlim> {
                i4
            }.AsReadOnly();
            var args2 = new List <TypeSlim> {
                i8, i4
            }.AsReadOnly();
            var args3 = new List <TypeSlim> {
                i4, i8, i4
            }.AsReadOnly();

            var mtd_0_i4i8_i4_0 = new SimpleMethodInfoSlim(tp1, "Qux0", args0, i4);
            var mtd_0_i4i8_i4_1 = new SimpleMethodInfoSlim(tp1, "Qux0", args0, i4);

            var mtd_0_i4i8_i8_0 = new SimpleMethodInfoSlim(tp1, "Qux0", args0, i8);
            var mtd_0_i4i8_i8_1 = new SimpleMethodInfoSlim(tp1, "Qux0", args0, i8);

            var mtd_0_i4_i4_0     = new SimpleMethodInfoSlim(tp1, "Qux0", args1, i4);
            var mtd_0_i8i4_i4_0   = new SimpleMethodInfoSlim(tp1, "Qux0", args2, i4);
            var mtd_0_i4i8i4_i4_0 = new SimpleMethodInfoSlim(tp1, "Qux0", args3, i4);

            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i4_0, mtd_0_i4i8_i4_0));
            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i4_0, mtd_0_i4i8_i4_1));
            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i4_1, mtd_0_i4i8_i4_0));

            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i4i8_i8_0));
            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i4i8_i8_1));
            Assert.IsTrue(eq.Equals(mtd_0_i4i8_i8_1, mtd_0_i4i8_i8_0));

            Assert.IsFalse(eq.Equals(mtd_0_i4i8_i4_0, mtd_0_i4i8_i8_0));
            Assert.IsFalse(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i4i8_i4_0));

            Assert.IsFalse(eq.Equals(mtd_0_i4_i4_0, mtd_0_i4i8_i8_0));
            Assert.IsFalse(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i4_i4_0));

            Assert.IsFalse(eq.Equals(mtd_0_i8i4_i4_0, mtd_0_i4i8_i8_0));
            Assert.IsFalse(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i8i4_i4_0));

            Assert.IsFalse(eq.Equals(mtd_0_i4i8i4_i4_0, mtd_0_i4i8_i8_0));
            Assert.IsFalse(eq.Equals(mtd_0_i4i8_i8_0, mtd_0_i4i8i4_i4_0));

            Assert.AreEqual(eq.GetHashCode(mtd_0_i4i8_i4_0), eq.GetHashCode(mtd_0_i4i8_i4_0));
            Assert.AreEqual(eq.GetHashCode(mtd_0_i4i8_i4_0), eq.GetHashCode(mtd_0_i4i8_i4_1));
            Assert.AreEqual(eq.GetHashCode(mtd_0_i4i8_i4_1), eq.GetHashCode(mtd_0_i4i8_i4_1));
        }
Exemplo n.º 8
0
 internal TryExpressionSlim(TypeSlim type, ExpressionSlim body, ExpressionSlim @finally, ExpressionSlim fault, ReadOnlyCollection <CatchBlockSlim> handlers)
 {
     Type     = type;
     Body     = body;
     Handlers = handlers;
     Finally  = @finally;
     Fault    = fault;
 }
Exemplo n.º 9
0
 internal SwitchExpressionSlim(TypeSlim type, ExpressionSlim switchValue, ExpressionSlim defaultBody, MethodInfoSlim comparison, ReadOnlyCollection <SwitchCaseSlim> cases)
 {
     Type        = type;
     SwitchValue = switchValue;
     DefaultBody = defaultBody;
     Comparison  = comparison;
     Cases       = cases;
 }
Exemplo n.º 10
0
        public void TypeSlimVisitor_Visit_GenericParameter()
        {
            var gp = TypeSlim.GenericParameter("T");

            var visitor = new TypeSlimVisitor();

            Assert.AreSame(gp, visitor.Visit(gp));
        }
        public void TypeSlimEqualityComparer_Equals()
        {
            var eq = TypeSlimEqualityComparer.Default;

            Assert.IsTrue(eq.Equals(null, null));
            Assert.IsFalse(eq.Equals(null, SlimType));
            Assert.IsFalse(eq.Equals(SlimType, null));
            Assert.IsFalse(eq.Equals(SlimType, TypeSlim.Array(SlimType)));
        }
Exemplo n.º 12
0
        internal static ArrayTypeSlim CreateMultiDimensional(TypeSlim elementType, int rank)
        {
            RequireNotNull(elementType, nameof(elementType));

            if (rank <= 0)
                throw new ArgumentOutOfRangeException(nameof(rank));

            return new MultiDimensionalArrayTypeSlim(elementType, rank);
        }
Exemplo n.º 13
0
        public override TypeSlim ToType(DeserializationDomain domain, params TypeSlim[] genericArguments)
        {
            if (_type == null)
            {
                _type = TypeSlim.Simple(domain.GetAssembly(_assembly), _typeName);
            }

            return(_type);
        }
Exemplo n.º 14
0
            public override ObjectSlim Update(object value, TypeSlim typeSlim)
            {
                if (value != Value || typeSlim != TypeSlim)
                {
                    return(new ReducibleObjectSlim <TLifted>((TLifted)value, typeSlim, ReduceFactory));
                }

                return(this);
            }
Exemplo n.º 15
0
        public void TypeSlimVisitor_Visit_Collection_MakeNewCollection()
        {
            var visitor = new B();
            var types = new List <TypeSlim> {
                TypeSlim.Simple(new AssemblySlim("Foo"), "Bar"), SlimType, SlimType
            }.AsReadOnly();

            Assert.AreNotSame(types, visitor.Visit(types));
        }
Exemplo n.º 16
0
        public void TypeSlimToTypeConverter_VisitGenericParameter_ThrowsInvalidOperation()
        {
            var visitor = new TypeSlimToTypeConverter(DefaultReflectionProvider.Instance);

            visitor.Push(new Dictionary <TypeSlim, Type>());
            var param = TypeSlim.GenericParameter("T");

            Assert.ThrowsException <InvalidOperationException>(() => visitor.Visit(param));
        }
Exemplo n.º 17
0
            public override ObjectSlim Update(object value, TypeSlim typeSlim)
            {
                if (value != Value || typeSlim != TypeSlim)
                {
                    return(new LiftableObjectSlim(value, typeSlim, OriginalType));
                }

                return(this);
            }
Exemplo n.º 18
0
        public void MemberInfoSlimEqualityComparer_Property_Index()
        {
            var tq = new TypeSlimEqualityComparer();
            var eq = new MemberInfoSlimEqualityComparer(tq);

            var asm = new AssemblySlim("foo");

            var tp1 = TypeSlim.Simple(asm, "bar");

            var i4 = typeof(int).ToTypeSlim();
            var i8 = typeof(long).ToTypeSlim();

            var indxs0 = new List <TypeSlim> {
                i4
            }.AsReadOnly();
            var indxs1 = new List <TypeSlim> {
                i8
            }.AsReadOnly();
            var indxs2 = new List <TypeSlim> {
                i4, i8
            }.AsReadOnly();
            var indxs3 = new List <TypeSlim> {
                i8, i4
            }.AsReadOnly();

            var prp_i4_0_0 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs0, canWrite: true);
            var prp_i4_0_1 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs0, canWrite: true);
            var prp_i4_1_0 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs1, canWrite: true);
            var prp_i4_2_0 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs2, canWrite: true);
            var prp_i4_3_0 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs3, canWrite: true);
            var prp_i4_3_1 = PropertyInfoSlim.Make(tp1, "Item", i4, indxs3, canWrite: true);

            var prp_i8_0_0 = PropertyInfoSlim.Make(tp1, "Item", i8, indxs0, canWrite: true);
            var prp_i8_1_0 = PropertyInfoSlim.Make(tp1, "Item", i8, indxs1, canWrite: true);
            var prp_i8_2_0 = PropertyInfoSlim.Make(tp1, "Item", i8, indxs2, canWrite: true);
            var prp_i8_3_0 = PropertyInfoSlim.Make(tp1, "Item", i8, indxs3, canWrite: true);

            Assert.IsTrue(eq.Equals(prp_i4_0_0, prp_i4_0_0));
            Assert.IsTrue(eq.Equals(prp_i4_0_0, prp_i4_0_1));
            Assert.IsTrue(eq.Equals(prp_i4_0_1, prp_i4_0_0));
            Assert.IsTrue(eq.Equals(prp_i4_3_0, prp_i4_3_1));
            Assert.IsTrue(eq.Equals(prp_i4_3_1, prp_i4_3_0));

            Assert.IsFalse(eq.Equals(prp_i4_0_0, prp_i4_1_0));
            Assert.IsFalse(eq.Equals(prp_i4_1_0, prp_i4_0_0));
            Assert.IsFalse(eq.Equals(prp_i4_2_0, prp_i4_3_0));
            Assert.IsFalse(eq.Equals(prp_i4_3_0, prp_i4_2_0));

            Assert.IsFalse(eq.Equals(prp_i4_0_0, prp_i8_0_0));
            Assert.IsFalse(eq.Equals(prp_i4_1_0, prp_i8_1_0));
            Assert.IsFalse(eq.Equals(prp_i4_2_0, prp_i8_2_0));
            Assert.IsFalse(eq.Equals(prp_i4_3_0, prp_i8_3_0));

            Assert.AreEqual(eq.GetHashCode(prp_i4_0_0), eq.GetHashCode(prp_i4_0_1));
            Assert.AreEqual(eq.GetHashCode(prp_i4_3_0), eq.GetHashCode(prp_i4_3_1));
        }
Exemplo n.º 19
0
        /// <summary>
        /// The equals method for comparing against other class instances.
        /// </summary>
        /// <param name="other">The other instance.</param>
        /// <returns><b>true</b> if the given instance equals this instance, <b>false</b> otherwise.</returns>
        public override bool Equals(TypeSlim other)
        {
            if (other is SimpleTypeSlimBase s)
            {
                return(Kind == s.Kind &&
                       Name == s.Name &&
                       Assembly?.Name == s.Assembly?.Name);
            }

            return(false);
        }
Exemplo n.º 20
0
        // NB: Update is kept internal for now until we make this available as a proper API.
        //     It's only used by the visitor at this point.

        /// <summary>
        /// Returns a new lightweight representation of an array type, or the current instance if nothing has changed.
        /// </summary>
        /// <param name="elementType">The new element type.</param>
        /// <returns>A lightweight representation of an array type with the specified element type.</returns>
        internal ArrayTypeSlim Update(TypeSlim elementType)
        {
            if (elementType != ElementType)
            {
                return Rewrite(elementType);
            }
            else
            {
                return this;
            }
        }
#pragma warning restore format

        /// <summary>
        /// Gets the reactive type from a type name.
        /// </summary>
        /// <param name="typeSlim">The type.</param>
        /// <returns>The reactive entity type.</returns>
        public static ReactiveEntityType FromTypeSlim(TypeSlim typeSlim)
        {
            if (typeSlim == null)
            {
                throw new ArgumentNullException(nameof(typeSlim));
            }

            if (typeSlim is GenericTypeSlim genericTypeSlim)
            {
                var definition = genericTypeSlim.GenericTypeDefinition;

                if (SlimObservableType.Equals(definition))
                {
                    return(ReactiveEntityType.Observable);
                }
                else if (SlimObserverType.Equals(definition))
                {
                    return(ReactiveEntityType.Observer);
                }
                else if (SlimSubjectFactoryType.Equals(definition))
                {
                    return(ReactiveEntityType.StreamFactory);
                }
                else if (SlimSubjectType1.Equals(definition) || SlimSubjectType2.Equals(definition))
                {
                    return(ReactiveEntityType.Stream);
                }
                else if (SlimSubscriptionFactoryType2.Equals(definition))
                {
                    return(ReactiveEntityType.SubscriptionFactory);
                }
                else if (SlimFuncType.Equals(definition))
                {
                    var argCount = genericTypeSlim.GenericArgumentCount;
                    var lastArg  = genericTypeSlim.GetGenericArgument(argCount - 1);

                    var parameterizedType = FromTypeSlim(lastArg);
                    if (parameterizedType != ReactiveEntityType.None)
                    {
                        return(ReactiveEntityType.Func | parameterizedType);
                    }
                }
            }
            else if (SlimSubscriptionType.Equals(typeSlim))
            {
                return(ReactiveEntityType.Subscription);
            }
            else if (SlimSubscriptionFactoryType1.Equals(typeSlim))
            {
                return(ReactiveEntityType.SubscriptionFactory);
            }

            return(ReactiveEntityType.None);
        }
Exemplo n.º 22
0
        public override TypeSlim ToType(DeserializationDomain domain, TypeSlim[] genericArguments)
        {
            if (_type == null)
            {
                var elementType = domain.GetType(_elementType).ToType(domain, genericArguments);

                _type = _rank == null?TypeSlim.Array(elementType) : TypeSlim.Array(elementType, _rank.Value);
            }

            return(_type);
        }
Exemplo n.º 23
0
 protected override TypeSlim VisitSimple(SimpleTypeSlim type)
 {
     if (type == SlimType)
     {
         return(TypeSlim.Simple(new AssemblySlim("Foo"), "Bar"));
     }
     else
     {
         return(base.VisitSimple(type));
     }
 }
Exemplo n.º 24
0
 protected override TypeSlim VisitSimple(SimpleTypeSlim type)
 {
     if (type == SlimType)
     {
         return(TypeSlim.Array(type));
     }
     else
     {
         return(base.VisitSimple(type));
     }
 }
Exemplo n.º 25
0
 /// <summary>
 /// Creates a slim representation of a type field.
 /// </summary>
 /// <param name="originalField">The original field.</param>
 /// <param name="declaringTypeSlim">The slim representation of the declaring type.</param>
 /// <param name="fieldTypeSlim">The slim representation of the field type.</param>
 /// <returns>The slim representation of the field.</returns>
 protected override FieldInfoSlim GetFieldCore(FieldInfo originalField, TypeSlim declaringTypeSlim, TypeSlim fieldTypeSlim)
 {
     if (!originalField.DeclaringType.IsDefined(typeof(KnownTypeAttribute), inherit: false))
     {
         var fieldMapping = originalField.GetCustomAttribute <MappingAttribute>(inherit: false);
         if (fieldMapping != null)
         {
             return(declaringTypeSlim.GetField(fieldMapping.Uri, fieldTypeSlim));
         }
     }
     return(base.GetFieldCore(originalField, declaringTypeSlim, fieldTypeSlim));
 }
Exemplo n.º 26
0
        internal static ConstantExpressionSlim Make(ObjectSlim value, TypeSlim type)
        {
            // NB: The overloaded operator == on TypeSlim can be expensive, so we'll just
            //     look for reference equality.

            if (ReferenceEquals(value.TypeSlim, type))
            {
                return(new ConstantExpressionSlim(value));
            }

            return(new TypedConstantExpressionSlim(value, type));
        }
Exemplo n.º 27
0
        public void GenericTypeSlim_Optimized1()
        {
            var arg1 = typeof(int).ToTypeSlim();

            var gen1 = TypeSlim.Generic((GenericDefinitionTypeSlim)typeof(Func <>).ToTypeSlim(), arg1);
            var gen2 = TypeSlim.Generic((GenericDefinitionTypeSlim)typeof(Func <>).ToTypeSlim(), new[] { arg1 });
            var gen3 = TypeSlim.Generic((GenericDefinitionTypeSlim)typeof(Func <>).ToTypeSlim(), new ReadOnlyCollection <TypeSlim>(new[] { arg1 }));

            foreach (var gen in new[] { gen1, gen2, gen3 })
            {
                AssertOptimized(gen, 1, arg1);
            }
        }
Exemplo n.º 28
0
        // REVIEW: The asymmetry here is slightly disturbing. We should review the lift/reduce constructs here.

        /// <summary>
        /// Creates a new slim representation of a constant value that can be lifted to a Bonsai representation.
        /// </summary>
        /// <param name="value">The underlying value that can be lifted to a Bonsai representation.</param>
        /// <param name="typeSlim">The slim type to use in the Bonsai representation.</param>
        /// <param name="type">The CLR type of the underlying value.</param>
        /// <returns>A new slim representation of a constant value that can be lifted to a Bonsai representation.</returns>
        public static ObjectSlim Create(object value, TypeSlim typeSlim, Type type)
        {
            if (typeSlim == null)
            {
                throw new ArgumentNullException(nameof(typeSlim));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            return(new LiftableObjectSlim(value, typeSlim, type));
        }
Exemplo n.º 29
0
        /// <summary>
        /// Creates a new slim representation of a constant value that can be reduced to a CLR object representation.
        /// </summary>
        /// <param name="liftedValue">The lifted value that can be reduced to a CLR object representation.</param>
        /// <param name="typeSlim">The slim type to use in the Bonsai representation.</param>
        /// <param name="reduceFactory">The factory used to obtain a strongly typed reducer to convert the object to a CLR object representation.</param>
        /// <returns>A new slim representation of a constant value that can be reduced to a CLR object representation.</returns>
        public static ObjectSlim Create <TLifted>(TLifted liftedValue, TypeSlim typeSlim, Func <Type, Func <TLifted, object> > reduceFactory)
        {
            if (typeSlim == null)
            {
                throw new ArgumentNullException(nameof(typeSlim));
            }
            if (reduceFactory == null)
            {
                throw new ArgumentNullException(nameof(reduceFactory));
            }

            return(new ReducibleObjectSlim <TLifted>(liftedValue, typeSlim, reduceFactory));
        }
        public void TypeSlimEqualityComparator_Pooling()
        {
            // NB: This relies on some implementation details of collection APIs in .NET. The TypeSlimEqualityComparator
            //     used a HashSet<T> and a Dictionary<K, V> which both have a version field we can use to assert progress
            //     in a white-box manner.

            var fields = (from f in typeof(TypeSlimEqualityComparator).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                          where typeof(ICollection).IsAssignableFrom(f.FieldType)
                          let v = f.FieldType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single(i => i.FieldType == typeof(int) && i.Name.Contains("version"))
                                  select(Collection: f, Version: v))
                         .ToArray();

            Assert.IsTrue(fields.Length > 0);

            var p1 = SlimType.GetProperty("Foo", SlimType, EmptyReadOnlyCollection <TypeSlim> .Instance, canWrite: true);
            var s1 = TypeSlim.Structural(new List <PropertyInfoSlim> {
                p1
            }.AsReadOnly(), hasValueEqualitySemantics: true, StructuralTypeSlimKind.Record);
            var s2 = TypeSlim.Structural(new List <PropertyInfoSlim> {
                p1
            }.AsReadOnly(), hasValueEqualitySemantics: true, StructuralTypeSlimKind.Record);

            var pool = new ObjectPool <TypeSlimEqualityComparator>(() => new TypeSlimEqualityComparator(), 1);

            var obj = default(TypeSlimEqualityComparator);

            int[] v1, v2, v3;

            using (var eq = pool.New())
            {
                obj = eq.Object;

                v1 = GetVersions(obj);

                Assert.IsTrue(obj.Equals(s1, s2));

                v2 = GetVersions(obj); // NB: Equals for structural types will touch the tracking data structures.
            }

            v3 = GetVersions(obj); // NB: The Clear method should clear all tracking data structures.

            AssertVersionsChanged(v1, v2);
            AssertVersionsChanged(v2, v3);

            int[] GetVersions(TypeSlimEqualityComparator eq)
            {
                return((from f in fields
                        let collection = f.Collection.GetValue(eq)
                                         let version = (int)f.Version.GetValue(collection)
                                                       select version).ToArray());
            }