I've been trying to come up with a generic shape design that would support shape-shape interactions (like Intersect), **based on the shape's type**.

So a common class/interface was needed, but a problem arises from shape types since not all shapes have common properties (eg. Circle is composed of a point and a radius, while polygons are composed of multiple points) so each pair of shape types has to have their own Intersect method.

After a lot of reading up on the subject of generics (and the like), i've come up with the following structure:

Collection class for storing delegates to shape Intersect methods

    class IRdelegateCollection<T> // IntersectResult delegate collection
    {
        public delegate IntersectResult IntersectAction<in U>(T a, U b);

        Dictionary<Type, Delegate> _jumpTable;
        public IRdelegateCollection()
        {
            _jumpTable = new Dictionary<Type, Delegate>();
        }
        public IRdelegateCollection(Dictionary<Type, Delegate> jumpTable)
        {
            _jumpTable = jumpTable;
        }
        public void Set<U>(IntersectAction<U> action)
        {
            if (_jumpTable.ContainsKey(typeof(U)))
                _jumpTable[typeof(U)] = action;
            else
                _jumpTable.Add(typeof(U), action);
        }
        public IntersectAction<U> Get<U>()
        {
            if (!_jumpTable.ContainsKey(typeof(U)))
            {
                return null;
            }
            return _jumpTable[typeof(U)] as IntersectAction<U>;
        }
    }


Interfaces

    interface IShape
    {
        IntersectResult Intersects(IShape shape, out bool flipped);
        IntersectResult Intersects<T>(IShape<T> shape, out bool flipped);
    }
    interface IShape<T> : IShape
    {
        T Instance { get; }
        IRdelegateCollection<T> IC { get; }
    }


Base Shape class (all shapes will derive from this, although i guess they don't have to as long as they have their own IShape interface implementation)

    abstract class Shape<T> : IShape<T>
    {
        public abstract T Instance { get; } // shape instance
        public abstract IRdelegateCollection<T> IC { get; } // shape type's intersection delegate collection                

        public IntersectResult Intersects(IShape shape, out bool flipped)
        {
            IntersectResult r = shape.Intersects<T>(this, out flipped); // call the other shape's intersect method, specifying our type
            flipped = !flipped; // results are flipped since we're calling the other shape's method
            return r;
        }
        public IntersectResult Intersects<T2>(IShape<T2> shape, out bool flipped)
        {
            flipped = false;
            var del1vs2 = IC.Get<T2>();
            if (del1vs2 != null) // we have the intersection delegate
                return del1vs2(Instance, shape.Instance);

            var del2vs1 = shape.IC.Get<T>(); // we dont have the delegate, try get the other shape's intersection delegate
            if (del2vs1 != null)
            {
                flipped = true; // we're returning the results of other shape's delegate, mark it as flipped
                return del2vs1(shape.Instance, Instance);
            }

            // neither of the two shapes have the intersection delegate
            return new IntersectResult();
        }        
    }


Some concrete shape definitions. (ShapeA does not have delegate for ShapeA-ShapeB intersection, but since ShapeB has one for ShapeB-ShapeA thats the one that gets called when intersecting ShapeB on ShapeA)

    class ShapeA : Shape<ShapeA>
    {
        static IRdelegateCollection<ShapeA> _ic =
            new IRdelegateCollection<ShapeA>(
                new Dictionary<Type, Delegate>()
                {
                    { typeof(ShapeA), new IRdelegateCollection<ShapeA>.IntersectAction<ShapeA>(MathCol.AIntersectsA) }
                }
            );
        public override ShapeA Instance { get { return this; } }
        public override IRdelegateCollection<ShapeA> IC { get { return _ic; } }
    }
    class ShapeB : Shape<ShapeB>
    {
        static IRdelegateCollection<ShapeB> _ic =
           new IRdelegateCollection<ShapeB>(
               new Dictionary<Type, Delegate>()
               {
                        { typeof(ShapeB), new IRdelegateCollection<ShapeB>.IntersectAction<ShapeB>(MathCol.BIntersectsB) },
                        { typeof(ShapeA), new IRdelegateCollection<ShapeB>.IntersectAction<ShapeA>(MathCol.BIntersectsA) }
               }
           );
        public override ShapeB Instance { get { return this; } }
        public override IRdelegateCollection<ShapeB> IC { get { return _ic; } }
    }

With this kind of structure i can have a list of shapes and be able to intersect them appropriately without having to manually check their types.

    ShapeA a = new ShapeA();
    ShapeB b = new ShapeB();
    bool flipped = false;

    // These are called via .Intersects<T>(T shape, out bool flipped)
    a.Intersects(a, out flipped); //calls AintersectsA, flipped: False
    a.Intersects(b, out flipped); //calls BintersectsA, flipped: True
    b.Intersects(a, out flipped); //calls BintersectsA, flipped: False
    b.Intersects(b, out flipped); //calls BintersectsB, flipped: False

    List<IShape> shapes = new List<IShape>();
    shapes.Add(a);
    shapes.Add(b);
    // These are called via .Intersects(IShape shape, out bool flipped)
    shapes[0].Intersects(shapes[0], out flipped); //calls AintersectsA, flipped: True
    shapes[0].Intersects(shapes[1], out flipped); //calls BintersectsA, flipped: True
    shapes[1].Intersects(shapes[0], out flipped); //calls BintersectsA, flipped: False
    shapes[1].Intersects(shapes[1], out flipped); //calls BintersectsB, flipped: True

So there it is, now what i would like to know is:

 1. Is this design appropriate for my requirement (having base shape that can intersect other shapes based on their subtype)?
 2. The double interface - is this considered bad design (since `IShape`'s method accepts `IShape<T>` argument and `IShape<T>` is derived from `IShape`)?
Note: i've also tried an alternative design where the `IShape.Intersect<T>` parameter was the abstract class `Shape<T>` but that didn't seem right as well.
 3. I've had constraints `where T : IShape` on both the interface, abstract class `Shape<T>` and `IRdelegateCollection<T>` since i was trying to avoid the `T Instance` which is used in the `Intersection<T>()` method, but the compiler still had problems converting `Shape<T> to T`.
 - Is there a way to use the sahpes directly in the delegate invokation of the `Shape<T>.Intersects<T2>` method? (preferably: `del1v2(this, shape)` - was throwing the above mentioned error, even with the constraints all over the place)
 - Should there be constraints of `where T : IShape` on all the `T`s? (There does not appear to be any advantage to constraining it)
 4. Class `IRdelegateCollection<T>` uses a "jump table". My implementation needs a `_jumpTable.ContainsKey(typeof(U))` check for both setting and getting. Is there a better way of making this kind of jump table?