ImMap

We found 10 examples in language CSharp for this search. You will see 48 fragments of code.

Other methods


            public V2.ImMap<string> AddOrUpdate_v2()
            {
                var map = V2.ImMap<string>.Empty;

                for (var i = 0; i < Count; i++)
                    map = V2.ImMap.AddOrUpdate(map, i, i.ToString());

                return map;
            }


// A simple image area click handler
        private void imMap_Click(object sender, ImageMapClickEventArgs e)
        {
            MessageBox.Show(String.Format(
                "You clicked area #{0} ({1}) at point {2}, {3}",
                    e.AreaIndex + 1, imMap.Areas[e.AreaIndex].ToolTip,
                    e.XCoordinate, e.YCoordinate), "Image Map Clicked",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>Returns true if array is null or have no items.</summary> <typeparam name="T">Type of array item.</typeparam>
        /// <param name="source">Source array to check.</param> <returns>True if null or has no items, false otherwise.</returns>
        public static bool IsNullOrEmpty<T>(this T[] source)
        {
            return source == null || source.Length == 0;
        }

        /// <summary>Returns empty array instead of null, or source array otherwise.</summary> <typeparam name="T">Type of array item.</typeparam>
        /// <param name="source">Source array.</param> <returns>Empty array or source.</returns>
        public static T[] EmptyIfNull<T>(this T[] source)
        {
            return source ?? Empty<T>();
        }

        /// <summary>Returns source enumerable if it is array, otherwise converts source to array.</summary>
        /// <typeparam name="T">Array item type.</typeparam>
        /// <param name="source">Source enumerable.</param>
        /// <returns>Source enumerable or its array copy.</returns>
        public static T[] ToArrayOrSelf<T>(this IEnumerable<T> source)
        {
            var array = source as T[];
            return array ?? source.ToArray();
        }

        /// <summary>Returns new array consisting from all items from source array then all items from added array.
        /// If source is null or empty, then added array will be returned.
        /// If added is null or empty, then source will be returned.</summary>
        /// <typeparam name="T">Array item type.</typeparam>
        /// <param name="source">Array with leading items.</param>
        /// <param name="added">Array with following items.</param>
        /// <returns>New array with items of source and added arrays.</returns>
        public static T[] Append<T>(this T[] source, params T[] added)
        {
            if (added == null || added.Length == 0)
                return source;
            if (source == null || source.Length == 0)
                return added;
            var result = new T[source.Length + added.Length];
            Array.Copy(source, 0, result, 0, source.Length);
            if (added.Length == 1)
                result[source.Length] = added[0];
            else
                Array.Copy(added, 0, result, source.Length, added.Length);
            return result;
        }

        /// <summary>Returns new array with <paramref name="value"/> appended, 
        /// or <paramref name="value"/> at <paramref name="index"/>, if specified.
        /// If source array could be null or empty, then single value item array will be created despite any index.</summary>
        /// <typeparam name="T">Array item type.</typeparam>
        /// <param name="source">Array to append value to.</param>
        /// <param name="value">Value to append.</param>
        /// <param name="index">(optional) Index of value to update.</param>
        /// <returns>New array with appended or updated value.</returns>
        public static T[] AppendOrUpdate<T>(this T[] source, T value, int index = -1)
        {
            if (source == null || source.Length == 0)
                return new[] { value };
            var sourceLength = source.Length;
            index = index < 0 ? sourceLength : index;
            var result = new T[index < sourceLength ? sourceLength : sourceLength + 1];
            Array.Copy(source, result, sourceLength);
            result[index] = value;
            return result;
        }

        /// <summary>Calls predicate on each item in <paramref name="source"/> array until predicate returns true,
        /// then method will return this item index, or if predicate returns false for each item, method will return -1.</summary>
        /// <typeparam name="T">Type of array items.</typeparam>
        /// <param name="source">Source array: if null or empty, then method will return -1.</param>
        /// <param name="predicate">Delegate to evaluate on each array item until delegate returns true.</param>
        /// <returns>Index of item for which predicate returns true, or -1 otherwise.</returns>
        public static int IndexOf<T>(this T[] source, Func<T, bool> predicate)
        {
            if (source != null && source.Length != 0)
                for (var i = 0; i < source.Length; ++i)
                    if (predicate(source[i]))
                        return i;
            return -1;
        }


        /// Adds or updates the value by key in the map, always returns a modified map
        [MethodImpl((MethodImplOptions)256)]
        public ImMap<V> AddOrUpdate(int key, V value) =>
            ReferenceEquals(this, Empty)
                ? new ImMap<V>(key, value)
                : this is ImMapTree<V> tree ?
                    (key == Key 
                        ? new ImMapTree<V>(key, new ImMap<V>(key, value), tree.Left, tree.Right, tree.Height)
                        : tree.AddOrUpdateLeftOrRight(key, value)) 
                : key > Key ? new ImMapTree<V>(Key, this, Empty, new ImMap<V>(key, value), 2) 
                : key < Key ? new ImMapTree<V>(Key, this, new ImMap<V>(key, value), Empty, 2)
                : new ImMap<V>(key, value);

        /// Outputs key value pair
        public override string ToString() => 
            ReferenceEquals(this, Empty) ? "empty" : Key + ":" + ((ValueOrData as ImMapTree<V>)?.ValueOrData ?? ValueOrData);

        // subj
        public ImMapTree<V> AddOrUpdateLeftOrRight(int key, V value)
        {
            if (key < Key)
            {
                if (ReferenceEquals(Left, Empty))
                    return new ImMapTree<V>(Key, ValueOrData, new ImMap<V>(key, value), Right, 2);

                var left = Left;
                var leftTree = left as ImMapTree<V>;
                if (leftTree == null) // left is the leaf
                    return key == left.Key
                        ? new ImMapTree<V>(Key, ValueOrData, new ImMap<V>(key, value), Right, Height)
                        : key < left.Key
                            ? (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(left.Key, left, new ImMap<V>(key, value), (ImMap<V>) ValueOrData, 2)
                                : new ImMapTree<V>(Key, ValueOrData,
                                    2, new ImMapTree<V>(left.Key, left, new ImMap<V>(key, value), Empty, 2), Right))
                            : (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(Key, ValueOrData,
                                    2, new ImMapTree<V>(left.Key, left, Empty, new ImMap<V>(key, value), 2), Right)
                                : new ImMapTree<V>(key, new ImMap<V>(key, value), left, (ImMap<V>)ValueOrData, 2));

                if (key == left.Key)
                    return new ImMapTree<V>(Key, ValueOrData,
                        new ImMapTree<V>(key, new ImMap<V>(key, value), leftTree.Left, leftTree.Right, leftTree.Height),
                        Right, Height);

                var newLeftTree = leftTree.AddOrUpdateLeftOrRight(key, value);
                if (newLeftTree.Height == leftTree.Height)
                    return new ImMapTree<V>(Key, ValueOrData, newLeftTree, Right, Height);

                var rightTree = Right as ImMapTree<V>;
                var rightHeight = rightTree?.Height ?? 1;
                if (newLeftTree.Height - 1 > rightHeight)
                {
                    // 1st fact - `leftLeft` and `leftRight` cannot be Empty otherwise we won't need to re-balance the left tree
                    // 2nd fact - either lefLeft or leftRight or both should be a tree

                    var leftLeft = newLeftTree.Left;
                    var leftLeftTree = leftLeft as ImMapTree<V>;
                    var leftRight = newLeftTree.Right;
                    var leftRightTree = leftRight as ImMapTree<V>;
                    if (leftLeftTree != null)
                    {
                        if (leftRightTree != null)
                        {
                            if (leftLeftTree.Height >= leftRightTree.Height)
                                return new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData,
                                    leftLeftTree.Height, leftLeftTree,
                                    new ImMapTree<V>(Key, ValueOrData, leftRightTree.Height, leftRightTree, rightHeight, Right));

                            return new ImMapTree<V>(leftRightTree.Key, leftRightTree.ValueOrData,
                                new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData, leftLeftTree.Height, leftLeftTree, leftRightTree.Left),
                                new ImMapTree<V>(Key, ValueOrData, leftRightTree.Right, rightHeight, Right));
                        }

                        // `leftLeft` is tree and `leftRight` is leaf - do a single rotation
                        return new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData,
                            leftLeftTree.Height, leftLeftTree,
                            new ImMapTree<V>(Key, ValueOrData, 1, leftRight, rightHeight, Right));
                    }

                    // `leftLeft` is leaf and `leftRight` is the tree - do a double rotation
                    // ReSharper disable once PossibleNullReferenceException
                    return new ImMapTree<V>(leftRightTree.Key, leftRightTree.ValueOrData,
                        new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData, 1, leftLeft, leftRightTree.Left),
                        new ImMapTree<V>(Key, ValueOrData, leftRightTree.Right, rightHeight, Right));
                }

                return new ImMapTree<V>(Key, ValueOrData, newLeftTree.Height, newLeftTree, rightHeight, Right);
            }
            else
            {
                if (ReferenceEquals(Right, Empty))
                    return new ImMapTree<V>(Key, ValueOrData, Left, new ImMap<V>(key, value), 2);

                var right = Right;
                var rightTree = right as ImMapTree<V>;
                if (rightTree == null) // the leaf
                    return key == right.Key
                        ? new ImMapTree<V>(Key, ValueOrData, Left, new ImMap<V>(key, value), Height)
                        : key < right.Key
                        ? (ReferenceEquals(Left, Empty)
                            ? new ImMapTree<V>(key, new ImMap<V>(key, value), (ImMap<V>)ValueOrData, right, 2)
                            : new ImMapTree<V>(Key, ValueOrData, Left,
                                2, new ImMapTree<V>(right.Key, right, new ImMap<V>(key, value), Empty, 2)))
                        : (ReferenceEquals(Left, Empty) 
                            ? new ImMapTree<V>(right.Key, right, (ImMap<V>)ValueOrData, new ImMap<V>(key, value), 2)
                            : new ImMapTree<V>(Key, ValueOrData, Left,
                                2, new ImMapTree<V>(right.Key, right, Empty, new ImMap<V>(key, value), 2)));

                if (key == right.Key)
                    return new ImMapTree<V>(Key, ValueOrData, Left,
                        new ImMapTree<V>(key, new ImMap<V>(key, value), rightTree.Left, rightTree.Right, rightTree.Height),
                        Height);

                var newRightTree = rightTree.AddOrUpdateLeftOrRight(key, value);
                if (newRightTree.Height == rightTree.Height)
                    return new ImMapTree<V>(Key, ValueOrData, Left, newRightTree, Height);

                var leftHeight = Left is ImMapTree<V> lt ? lt.Height : 1;
                if (newRightTree.Height - 1 > leftHeight)
                {
                    var rightLeft = newRightTree.Left;
                    var rightLeftTree = rightLeft as ImMapTree<V>;
                    var rightRight = newRightTree.Right;
                    var rightRightTree = rightRight as ImMapTree<V>;
                    if (rightLeftTree != null)
                    {
                        if (rightRightTree != null)
                        {
                            if (rightRightTree.Height >= rightLeftTree.Height)
                            {
                                rightLeftTree = new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Height, rightLeft);
                                newRightTree.Left = rightLeftTree;
                                newRightTree.Height = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                                return newRightTree;
                                //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                                //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Height, rightLeft),
                                //    rightRightTree.Height, rightRight);
                            }

                            //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                            //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                            //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, rightRightTree.Height, rightRight));
                        }

                        // right-left is tree and right-right is leaf - use a double rotation
                        newRightTree.Left = rightLeftTree.Right;
                        var newRightLeftHeight = newRightTree.Left is ImMapTree<V> rl ? rl.Height : 1;
                        var newRightRightHeight = rightRightTree?.Height ?? 1;
                        newRightTree.Height = newRightLeftHeight > newRightRightHeight ? newRightLeftHeight + 1 : newRightRightHeight + 1;

                        return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                            new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                            newRightTree);
                        //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                        //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                        //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, 
                        //        rightRightTree?.Height ?? 1, rightRight));
                    }

                    // `rightLeft` is leaf node and `rightRight` is the tree - use a single rotation
                    rightLeftTree = new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, 1, rightLeft);
                    newRightTree.Left = rightLeftTree;
                    // ReSharper disable once PossibleNullReferenceException
                    newRightTree.Height = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                    return newRightTree;

                    //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                    //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, 1, rightLeft),
                    //    rightRightTree.Height, rightRight);
                }

                // Height does not changed
                return new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, newRightTree.Height, newRightTree);
            } 
        }
        /// Returns true if key is found and sets the value.
        [MethodImpl((MethodImplOptions)256)]
        public static bool TryFind<V>(this ImMap<V> map, int key, out V value) where V : class
        {
            while (map is ImMapTree<V> mapTree)
            {
                if (key < mapTree.Key)
                    map = mapTree.Left;
                else if (key > mapTree.Key)
                    map = mapTree.Right;
                else
                {
                    value = (V)((ImMap<V>)mapTree.ValueOrData).ValueOrData;
                    return true;
                }
            }

            if (!ReferenceEquals(map, ImMap<V>.Empty) && map.Key == key)
            {
                value = (V)map.ValueOrData;
                return true;
            }

            value = null;
            return false;
        }

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

LamarCodeGeneration.Util.ImMap<V> : Object

Fields :

public static ImMap Empty

Methods :

public String ToString()
public Boolean get_IsEmpty()
public Int32 Count()
public Type GetType()
public Boolean Equals(Object obj = )
public Int32 GetHashCode()

ImMap

We found 10 examples in language CSharp for this search. You will see 47 fragments of code.

Other methods


            public V2.ImMap<string> AddOrUpdate_v2()
            {
                var map = V2.ImMap<string>.Empty;

                for (var i = 0; i < Count; i++)
                    map = V2.ImMap.AddOrUpdate(map, i, i.ToString());

                return map;
            }


// A simple image area click handler
        private void imMap_Click(object sender, ImageMapClickEventArgs e)
        {
            MessageBox.Show(String.Format(
                "You clicked area #{0} ({1}) at point {2}, {3}",
                    e.AreaIndex + 1, imMap.Areas[e.AreaIndex].ToolTip,
                    e.XCoordinate, e.YCoordinate), "Image Map Clicked",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
        }


        /// Outputs the key value pair
        public override string ToString() =>
            ReferenceEquals(this, Empty) ? "empty" : Key + ":" + Value;

        /// Adds or updates the value by key in the map, always returns a modified map
        [MethodImpl((MethodImplOptions)256)]
        public ImMap<V> AddOrUpdate(int key, V value) =>
            ReferenceEquals(this, Empty)
                ? new ImMap<V>(key, value)
                : this is ImMapTree<V> tree ?
                    (key == tree.Data.Key 
                        ? new ImMapTree<V>(new ImMap<V>(key, value), tree.Left, tree.Right, tree.Height)
                        : tree.AddOrUpdateLeftOrRight(key, value)) 
                    : key > Key ? new ImMapTree<V>(this, Empty, new ImMap<V>(key, value), 2) 
                    : key < Key ? new ImMapTree<V>(this, new ImMap<V>(key, value), Empty, 2)
                    : new ImMap<V>(key, value);

        /// Outputs the key value pair
        public override string ToString() =>
            ReferenceEquals(this, Empty) ? "empty" : Key + ":" + Data;

        // subj
        public ImMapTree<V> AddOrUpdateLeftOrRight(int key, V value)
        {
            if (key < Data.Key)
            {
                if (ReferenceEquals(Left, Empty))
                    return new ImMapTree<V>(Data, new ImMap<V>(key, value), Right, 2);

                var left = Left;
                var leftTree = left as ImMapTree<V>;
                if (leftTree == null) // left is the leaf
                    return key == left.Key
                        ? new ImMapTree<V>(Data, new ImMap<V>(key, value), Right, Height)
                        : key < left.Key
                            ? (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(left, new ImMap<V>(key, value), Data, 2)
                                : new ImMapTree<V>(Data, 2, new ImMapTree<V>(left, new ImMap<V>(key, value), Empty, 2), Right))
                            : (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(Data, 2, new ImMapTree<V>(left, Empty, new ImMap<V>(key, value), 2), Right)
                                : new ImMapTree<V>(new ImMap<V>(key, value), left, Data, 2));

                if (key == leftTree.Data.Key)
                    return new ImMapTree<V>(Data,
                        new ImMapTree<V>(new ImMap<V>(key, value), leftTree.Left, leftTree.Right, leftTree.Height),
                        Right, Height);

                var newLeftTree = leftTree.AddOrUpdateLeftOrRight(key, value);
                if (newLeftTree.Height == leftTree.Height)
                    return new ImMapTree<V>(Data, newLeftTree, Right, Height);

                var rightTree = Right as ImMapTree<V>;
                var rightHeight = rightTree?.Height ?? 1;
                if (newLeftTree.Height - 1 > rightHeight)
                {
                    // 1st fact - `leftLeft` and `leftRight` cannot be Empty otherwise we won't need to re-balance the left tree
                    // 2nd fact - either lefLeft or leftRight or both should be a tree

                    var leftLeft = newLeftTree.Left;
                    var leftLeftTree = leftLeft as ImMapTree<V>;
                    var leftRight = newLeftTree.Right;
                    var leftRightTree = leftRight as ImMapTree<V>;
                    if (leftLeftTree != null)
                    {
                        if (leftRightTree != null)
                        {
                            if (leftLeftTree.Height >= leftRightTree.Height)
                                return new ImMapTree<V>(newLeftTree.Data, leftLeftTree.Height, leftLeftTree,
                                    new ImMapTree<V>(Data, leftRightTree.Height, leftRightTree, rightHeight, Right));

                            return new ImMapTree<V>(leftRightTree.Data,
                                new ImMapTree<V>(newLeftTree.Data, leftLeftTree.Height, leftLeftTree, leftRightTree.Left),
                                new ImMapTree<V>(Data, leftRightTree.Right, rightHeight, Right));
                        }

                        // `leftLeft` is tree and `leftRight` is leaf - do a single rotation
                        return new ImMapTree<V>(newLeftTree.Data, leftLeftTree.Height, leftLeftTree,
                            new ImMapTree<V>(Data, 1, leftRight, rightHeight, Right));
                    }

                    // `leftLeft` is leaf and `leftRight` is the tree - do a double rotation
                    // ReSharper disable once PossibleNullReferenceException
                    return new ImMapTree<V>(leftRightTree.Data,
                        new ImMapTree<V>(newLeftTree.Data, 1, leftLeft, leftRightTree.Left),
                        new ImMapTree<V>(Data, leftRightTree.Right, rightHeight, Right));
                }

                return new ImMapTree<V>(Data, newLeftTree.Height, newLeftTree, rightHeight, Right);
            }
            else
            {
                if (ReferenceEquals(Right, Empty))
                    return new ImMapTree<V>(Data, Left, new ImMap<V>(key, value), 2);

                var right = Right;
                var rightTree = right as ImMapTree<V>;
                if (rightTree == null) // the leaf
                    return key == right.Key
                        ? new ImMapTree<V>(Data, Left, new ImMap<V>(key, value), Height)
                        : key < right.Key
                        ? (ReferenceEquals(Left, Empty)
                            ? new ImMapTree<V>(new ImMap<V>(key, value), Data, right, 2)
                            : new ImMapTree<V>(Data, Left,
                                2, new ImMapTree<V>(right, new ImMap<V>(key, value), Empty, 2)))
                        : (ReferenceEquals(Left, Empty) 
                            ? new ImMapTree<V>(right, Data, new ImMap<V>(key, value), 2)
                            : new ImMapTree<V>(Data, Left,
                                2, new ImMapTree<V>(right, Empty, new ImMap<V>(key, value), 2)));

                if (key == rightTree.Data.Key)
                    return new ImMapTree<V>(Data, Left,
                        new ImMapTree<V>(new ImMap<V>(key, value), rightTree.Left, rightTree.Right, rightTree.Height),
                        Height);

                var newRightTree = rightTree.AddOrUpdateLeftOrRight(key, value);
                if (newRightTree.Height == rightTree.Height)
                    return new ImMapTree<V>(Data, Left, newRightTree, Height);

                var leftHeight = Left is ImMapTree<V> lt ? lt.Height : 1;
                if (newRightTree.Height - 1 > leftHeight)
                {
                    var rightLeft = newRightTree.Left;
                    var rightLeftTree = rightLeft as ImMapTree<V>;
                    var rightRight = newRightTree.Right;
                    var rightRightTree = rightRight as ImMapTree<V>;
                    if (rightLeftTree != null)
                    {
                        if (rightRightTree != null)
                        {
                            if (rightRightTree.Height >= rightLeftTree.Height)
                            {
                                rightLeftTree = new ImMapTree<V>(Data, leftHeight, Left, rightLeftTree.Height, rightLeft);
                                newRightTree.Left = rightLeftTree;
                                newRightTree.Key = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                                return newRightTree;
                                //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                                //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Height, rightLeft),
                                //    rightRightTree.Height, rightRight);
                            }

                            //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                            //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                            //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, rightRightTree.Height, rightRight));
                        }

                        // right-left is tree and right-right is leaf - use a double rotation
                        newRightTree.Left = rightLeftTree.Right;
                        var newRightLeftHeight = newRightTree.Left is ImMapTree<V> rl ? rl.Height : 1;
                        var newRightRightHeight = rightRightTree?.Height ?? 1;
                        newRightTree.Key = newRightLeftHeight > newRightRightHeight ? newRightLeftHeight + 1 : newRightRightHeight + 1;

                        return new ImMapTree<V>(rightLeftTree.Data,
                            new ImMapTree<V>(Data, leftHeight, Left, rightLeftTree.Left),
                            newRightTree);
                        //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                        //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                        //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, 
                        //        rightRightTree?.Height ?? 1, rightRight));
                    }

                    // `rightLeft` is leaf node and `rightRight` is the tree - use a single rotation
                    rightLeftTree = new ImMapTree<V>(Data, leftHeight, Left, 1, rightLeft);
                    newRightTree.Left = rightLeftTree;
                    // ReSharper disable once PossibleNullReferenceException
                    newRightTree.Key = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                    return newRightTree;

                    //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                    //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, 1, rightLeft),
                    //    rightRightTree.Height, rightRight);
                }

                // Height does not changed
                return new ImMapTree<V>(Data, leftHeight, Left, newRightTree.Height, newRightTree);
            } 
        }
        /// Returns true if key is found and sets the value.
        [MethodImpl((MethodImplOptions)256)]
        public static bool TryFind<V>(this ImMap<V> map, int key, out V value)
        {
            int mapKey;
            while (map is ImMapTree<V> mapTree)
            {
                mapKey = mapTree.Data.Key;
                if (key < mapKey)
                    map = mapTree.Left;
                else if (key > mapKey)
                    map = mapTree.Right;
                else
                {
                    value = mapTree.Data.Value;
                    return true;
                }
            }

            if (!ReferenceEquals(map, ImMap<V>.Empty) && map.Key == key)
            {
                value = map.Value;
                return true;
            }

            value = default;
            return false;
        }


        /// Adds or updates the value by key in the map, always returns a modified map
        [MethodImpl((MethodImplOptions)256)]
        public ImMap<V> AddOrUpdate(int key, V value) =>
            ReferenceEquals(this, Empty)
                ? new ImMap<V>(key, value)
                : this is ImMapTree<V> tree ?
                    (key == Key 
                        ? new ImMapTree<V>(key, new ImMap<V>(key, value), tree.Left, tree.Right, tree.Height)
                        : tree.AddOrUpdateLeftOrRight(key, value)) 
                : key > Key ? new ImMapTree<V>(Key, this, Empty, new ImMap<V>(key, value), 2) 
                : key < Key ? new ImMapTree<V>(Key, this, new ImMap<V>(key, value), Empty, 2)
                : new ImMap<V>(key, value);

        /// Outputs key value pair
        public override string ToString() => 
            ReferenceEquals(this, Empty) ? "empty" : Key + ":" + ((ValueOrData as ImMapTree<V>)?.ValueOrData ?? ValueOrData);

        // subj
        public ImMapTree<V> AddOrUpdateLeftOrRight(int key, V value)
        {
            if (key < Key)
            {
                if (ReferenceEquals(Left, Empty))
                    return new ImMapTree<V>(Key, ValueOrData, new ImMap<V>(key, value), Right, 2);

                var left = Left;
                var leftTree = left as ImMapTree<V>;
                if (leftTree == null) // left is the leaf
                    return key == left.Key
                        ? new ImMapTree<V>(Key, ValueOrData, new ImMap<V>(key, value), Right, Height)
                        : key < left.Key
                            ? (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(left.Key, left, new ImMap<V>(key, value), (ImMap<V>) ValueOrData, 2)
                                : new ImMapTree<V>(Key, ValueOrData,
                                    2, new ImMapTree<V>(left.Key, left, new ImMap<V>(key, value), Empty, 2), Right))
                            : (ReferenceEquals(Right, Empty)
                                ? new ImMapTree<V>(Key, ValueOrData,
                                    2, new ImMapTree<V>(left.Key, left, Empty, new ImMap<V>(key, value), 2), Right)
                                : new ImMapTree<V>(key, new ImMap<V>(key, value), left, (ImMap<V>)ValueOrData, 2));

                if (key == left.Key)
                    return new ImMapTree<V>(Key, ValueOrData,
                        new ImMapTree<V>(key, new ImMap<V>(key, value), leftTree.Left, leftTree.Right, leftTree.Height),
                        Right, Height);

                var newLeftTree = leftTree.AddOrUpdateLeftOrRight(key, value);
                if (newLeftTree.Height == leftTree.Height)
                    return new ImMapTree<V>(Key, ValueOrData, newLeftTree, Right, Height);

                var rightTree = Right as ImMapTree<V>;
                var rightHeight = rightTree?.Height ?? 1;
                if (newLeftTree.Height - 1 > rightHeight)
                {
                    // 1st fact - `leftLeft` and `leftRight` cannot be Empty otherwise we won't need to re-balance the left tree
                    // 2nd fact - either lefLeft or leftRight or both should be a tree

                    var leftLeft = newLeftTree.Left;
                    var leftLeftTree = leftLeft as ImMapTree<V>;
                    var leftRight = newLeftTree.Right;
                    var leftRightTree = leftRight as ImMapTree<V>;
                    if (leftLeftTree != null)
                    {
                        if (leftRightTree != null)
                        {
                            if (leftLeftTree.Height >= leftRightTree.Height)
                                return new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData,
                                    leftLeftTree.Height, leftLeftTree,
                                    new ImMapTree<V>(Key, ValueOrData, leftRightTree.Height, leftRightTree, rightHeight, Right));

                            return new ImMapTree<V>(leftRightTree.Key, leftRightTree.ValueOrData,
                                new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData, leftLeftTree.Height, leftLeftTree, leftRightTree.Left),
                                new ImMapTree<V>(Key, ValueOrData, leftRightTree.Right, rightHeight, Right));
                        }

                        // `leftLeft` is tree and `leftRight` is leaf - do a single rotation
                        return new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData,
                            leftLeftTree.Height, leftLeftTree,
                            new ImMapTree<V>(Key, ValueOrData, 1, leftRight, rightHeight, Right));
                    }

                    // `leftLeft` is leaf and `leftRight` is the tree - do a double rotation
                    // ReSharper disable once PossibleNullReferenceException
                    return new ImMapTree<V>(leftRightTree.Key, leftRightTree.ValueOrData,
                        new ImMapTree<V>(newLeftTree.Key, newLeftTree.ValueOrData, 1, leftLeft, leftRightTree.Left),
                        new ImMapTree<V>(Key, ValueOrData, leftRightTree.Right, rightHeight, Right));
                }

                return new ImMapTree<V>(Key, ValueOrData, newLeftTree.Height, newLeftTree, rightHeight, Right);
            }
            else
            {
                if (ReferenceEquals(Right, Empty))
                    return new ImMapTree<V>(Key, ValueOrData, Left, new ImMap<V>(key, value), 2);

                var right = Right;
                var rightTree = right as ImMapTree<V>;
                if (rightTree == null) // the leaf
                    return key == right.Key
                        ? new ImMapTree<V>(Key, ValueOrData, Left, new ImMap<V>(key, value), Height)
                        : key < right.Key
                        ? (ReferenceEquals(Left, Empty)
                            ? new ImMapTree<V>(key, new ImMap<V>(key, value), (ImMap<V>)ValueOrData, right, 2)
                            : new ImMapTree<V>(Key, ValueOrData, Left,
                                2, new ImMapTree<V>(right.Key, right, new ImMap<V>(key, value), Empty, 2)))
                        : (ReferenceEquals(Left, Empty) 
                            ? new ImMapTree<V>(right.Key, right, (ImMap<V>)ValueOrData, new ImMap<V>(key, value), 2)
                            : new ImMapTree<V>(Key, ValueOrData, Left,
                                2, new ImMapTree<V>(right.Key, right, Empty, new ImMap<V>(key, value), 2)));

                if (key == right.Key)
                    return new ImMapTree<V>(Key, ValueOrData, Left,
                        new ImMapTree<V>(key, new ImMap<V>(key, value), rightTree.Left, rightTree.Right, rightTree.Height),
                        Height);

                var newRightTree = rightTree.AddOrUpdateLeftOrRight(key, value);
                if (newRightTree.Height == rightTree.Height)
                    return new ImMapTree<V>(Key, ValueOrData, Left, newRightTree, Height);

                var leftHeight = Left is ImMapTree<V> lt ? lt.Height : 1;
                if (newRightTree.Height - 1 > leftHeight)
                {
                    var rightLeft = newRightTree.Left;
                    var rightLeftTree = rightLeft as ImMapTree<V>;
                    var rightRight = newRightTree.Right;
                    var rightRightTree = rightRight as ImMapTree<V>;
                    if (rightLeftTree != null)
                    {
                        if (rightRightTree != null)
                        {
                            if (rightRightTree.Height >= rightLeftTree.Height)
                            {
                                rightLeftTree = new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Height, rightLeft);
                                newRightTree.Left = rightLeftTree;
                                newRightTree.Height = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                                return newRightTree;
                                //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                                //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Height, rightLeft),
                                //    rightRightTree.Height, rightRight);
                            }

                            //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                            //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                            //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, rightRightTree.Height, rightRight));
                        }

                        // right-left is tree and right-right is leaf - use a double rotation
                        newRightTree.Left = rightLeftTree.Right;
                        var newRightLeftHeight = newRightTree.Left is ImMapTree<V> rl ? rl.Height : 1;
                        var newRightRightHeight = rightRightTree?.Height ?? 1;
                        newRightTree.Height = newRightLeftHeight > newRightRightHeight ? newRightLeftHeight + 1 : newRightRightHeight + 1;

                        return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                            new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                            newRightTree);
                        //return new ImMapTree<V>(rightLeftTree.Key, rightLeftTree.ValueOrData,
                        //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, rightLeftTree.Left),
                        //    new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData, rightLeftTree.Right, 
                        //        rightRightTree?.Height ?? 1, rightRight));
                    }

                    // `rightLeft` is leaf node and `rightRight` is the tree - use a single rotation
                    rightLeftTree = new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, 1, rightLeft);
                    newRightTree.Left = rightLeftTree;
                    // ReSharper disable once PossibleNullReferenceException
                    newRightTree.Height = rightLeftTree.Height > rightRightTree.Height ? rightLeftTree.Height + 1 : rightRightTree.Height + 1;
                    return newRightTree;

                    //return new ImMapTree<V>(newRightTree.Key, newRightTree.ValueOrData,
                    //    new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, 1, rightLeft),
                    //    rightRightTree.Height, rightRight);
                }

                // Height does not changed
                return new ImMapTree<V>(Key, ValueOrData, leftHeight, Left, newRightTree.Height, newRightTree);
            } 
        }
        /// Returns true if key is found and sets the value.
        [MethodImpl((MethodImplOptions)256)]
        public static bool TryFind<V>(this ImMap<V> map, int key, out V value) where V : class
        {
            while (map is ImMapTree<V> mapTree)
            {
                if (key < mapTree.Key)
                    map = mapTree.Left;
                else if (key > mapTree.Key)
                    map = mapTree.Right;
                else
                {
                    value = (V)((ImMap<V>)mapTree.ValueOrData).ValueOrData;
                    return true;
                }
            }

            if (!ReferenceEquals(map, ImMap<V>.Empty) && map.Key == key)
            {
                value = (V)map.ValueOrData;
                return true;
            }

            value = null;
            return false;
        }

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

        /// <summary>Always a true condition.</summary>
        public static bool Always<T>(T _) => true;

        /// <summary>Identity function returning passed argument as result.</summary>
        public static T Id<T>(T x) => x;

        /// <summary>Piping</summary>
        public static R To<T, R>(this T x, Func<T, R> map) => map(x);

        /// <summary>Piping</summary>
        public static void Do<T>(this T x, Action<T> effect) => effect(x);

        /// Lift argument to Func without allocations ignoring the first argument.
        /// For example if you have `Func{T, R} = _ => instance`,
        /// you may rewrite it without allocations as `instance.ToFunc{A, R}` 
        public static R ToFunc<T, R>(this R result, T ignoredArg) => result;
        /// <summary>Provides result type inference for creation of lazy.</summary>
        public static Lazy<T> Of<T>(Func<T> valueFactory) => new Lazy<T>(valueFactory);

LamarCodeGeneration.Util.ImMap : Object

Methods :

public static ImMapEntry<V> Entry(Int32 hash = , V value = )
public static IEnumerable<ImMapEntry<V>> Enumerate(ImMap<V> map = , MapParentStack parents = null)
public static S ForEach(ImMap<V> map = , S state = , Action<ImMapEntry<V>, Int32, S> handler = , MapParentStack parents = null)
public static Void ForEach(ImMap<V> map = , Action<ImMapEntry<V>, Int32> handler = , MapParentStack parents = null)
public static S Fold(ImMap<V> map = , S state = , Func<ImMapEntry<V>, Int32, SS> handler = , MapParentStack parents = null)
public static S[] ToArray(ImMap<V> map = , Func<ImMapEntry<V>, S> selector = )
public static ImMapEntry ToArray(ImMap<V> map = )
public static Dictionary<Int32, V> ToDictionary(ImMap<V> map = )
public static ImMapEntry<V> GetSurePresentEntry(ImMap<V> map = , Int32 hash = )
public static ImMapEntry<V> GetEntryOrDefault(ImMap<V> map = , Int32 hash = )
public static V GetValueOrDefault(ImMap<V> map = , Int32 hash = )
public static Boolean TryFind(ImMap<V> map = , Int32 hash = , V& value = )
public static ImMap<V> AddOrGetEntry(ImMap<V> map = , ImMapEntry<V> newEntry = )
public static ImMap<V> AddOrUpdateEntry(ImMap<V> map = , ImMapEntry<V> newEntry = )
public static ImMap<V> AddOrUpdate(ImMap<V> map = , Int32 hash = , V value = )
public static ImMap<V> AddOrUpdate(ImMap<V> map = , Int32 hash = , V value = , Update<Int32, V> update = )
public static ImMap<V> Update(ImMap<V> map = , Int32 hash = , V value = )
public static ImMap<V> UpdateToDefault(ImMap<V> map = , Int32 hash = )
public static ImMap<V> AddOrKeepEntry(ImMap<V> map = , ImMapEntry<V> newEntry = )
public static ImMap<V> AddOrKeep(ImMap<V> map = , Int32 hash = , V value = )
public static ImMap<V> Remove(ImMap<V> map = , Int32 hash = )
public Type GetType()
public String ToString()
public Boolean Equals(Object obj = )
public Int32 GetHashCode()