Initial situation:
I am working with a proprietary framework (ESRI‘s ArcGIS Engine) which I want to extend with some new functionality. I’ve chosen to use extension methods in C# for this.
Shown below are the parts of the framework API that are relevant to this question:
+------------------------+ IGeometry
| IFeature <interface> | <interface>
+------------------------+ ^
| +Shape: IGeometry | |
+------------------------+ +---------+---------+
| |
IPoint IPolygon
<interface> <interface>
What I want to do:
I want to write an extension method for IFeature that will allow the following:
IFeature featureWithPointShape = ...,
featureWithPolygonShape = ...;
// this should work:
featureWithPointShape.DoSomethingWithPointFeature();
// this would ideally raise a compile-time error:
featureWithPolygonShape.DoSomethingWithPointFeature();
The problem is that both point and polygon shapes (IPoint and IPolygon) are wrapped in the same type (IFeature), for which the extension method is defined. The extension method has to be on IFeature because I can only get from an IFeature towards its IGeometry, but not vice versa.
Question:
While the type of an IFeature object’s Shape can easily be checked at run-time (see code example below), how could I achieve this type check at compile-time?
public static void DoSomethingWithPointFeature(this IFeature feature)
{
if (!(feature.Shape is IPoint))
{
throw new NotSupportedException("Method accepts only point features!");
}
... // (do something useful here)
}
(Is there possibly any way to use a generic wrapper type for IFeature, e.g. FeatureWithShape<IPoint>, define the extension method on this wrapper type, and then somehow turn all IFeature objects into this wrapper type?)
By definition, if you have an
IFeatureobject then itsShapeproperty can contain a value of any type that implementsIGeometry. If you’re in control of instantiation of theIFeatureobjects, then you can create your own generic class that implementsIFeatureor derive a class from a framework class that implementsIFeatureand then you can easily constrain the type ofShape. If you’re not in control of instantiation of these objects, then you’re probably stuck with a run-time check.If you happen to be using .NET 4.0, then you could use code contracts. The static checker would give you a compile-time warning if your extension method had a pre-condition on the type of
Shape.