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?