C#: Implicit type cast and class conflict

Standard

Before jumping into the topic, be clear of 3 things:

  1. This post is about implicit operator overloading.
  2. This is a C# only language feature.
  3. This post is gonna focus on how to resolve class conflict from multiple web references. If you are only wondering what implicit operator is, head to this intro page.

If you haven’t lost your way, then let the party begin 😀

The Problem

It’s perfectly fine if your have multiple classes using the same name in different name spaces. Although people usually don’t do that, but it could be a common case when adding multiple web references from the same provider.

One good example is the Bing Maps SOAP services. There are 4 SOAP services that you can reference from Bing Maps: Geocode, Imagery, Route, and Search. When you add one of these services to your project as a web reference, you need to give it a name space, and Visual Studio can auto generate the necessary proxy classes to be used with the web reference. If you add a second one, you need to give it a different name space. So far it’s pretty straight forward.

Now, the problem is, on Bing Maps server side, all of the services could be sharing some common classes in their back-end. These common classes are usually located under a common name space and all of the services just import this name space and use the same common classes. However, when you add the web references, you give a different name space to each one of them, and the generated classes are all under the name space you’ve given to the respective reference. Therefore, if you add all 4 Bing Maps web references, you will notice that there are some duplicate classes in each name space. For example, the ExecutionOptions class., it exists in all 4 name spaces.

When you have created an ExceptionOptions object of the Geocode service name space, and you want to use it with other services, the compiler complains that the object you’ve created can’t be used with them because it’s not in the correct name space.

The normal way of getting over this problem is that you re-create one ExceptionOptions object for each name space:

using MyApp.BingMaps.Geocode;
using MyApp.BingMaps.Imagery;
using MyApp.BingMaps.Route;
using MyApp.BingMaps.Search;

...

var exOptGeo = new BingMaps.Geocode.ExecutionOptions();
exOptGeo.SuppressFaults = true;
var exOptImg = new BingMaps.Imagery.ExecutionOptions();
exOptImg.SuppressFaults = true;
var exOptRte = new BingMaps.Route.ExecutionOptions();
exOptRte.SuppressFaults = true;
var exOptSrh = new BingMaps.Search.ExecutionOptions();
exOptSrh.SuppressFaults = true;

var geoReq = new GeocodeRequest { ExecutionOptions = exOptGeocode };
var imgReq = new ImageryRequest { ExecutionOptions = exOptImg };
var rteReq = new RouteRequest { ExecutionOptions = exOptRte };
var srhReq = new SearchRequest { ExecutionOptions = exOptSrh };

The code looks very repetitive in this way. It could be much more tedious if the object to re-create is complex.

Since the request objects are all different, we can’t really re-use them, but we can definitely re-use the ExecutionOptions object, which is 100% the same in all 4 name spaces.

Implicit Operator Overloading

Our solution is via Implicit Operator Overloading. The implicit operator is mainly used to eliminate unnecessary casts to improve source code readability. It does not require programmer to cast one type to another. In our case, it will be used to eliminate the re-creation code of each ExecutionOptions object.

Due to that all of the generated proxy classes are partial classes. Without modifying the generated code, we can create our own class file that extends any of the proxy classes like this:

namespace MyApp.BingMaps.Imagery
{
    public partial class ExecutionOptions
    {
        public int NewProperty() { get; set; }
    }
}

By extending the ExecutionOptions class like above, you can directly use NewProperty like any other generated properties:

var exOpt = new BingMaps.Geocode.ExecutionOptions();
exOpt.NewProperty = 1;

Knowing this, we can overload the implicit operator in this partial class as below:

namespace MyApp.BingMaps.Imagery
{
    public partial class ExecutionOptions
    {
        public static implicit operator ExecutionOptions(MyApp.BingMaps.Geocode.ExecutionOptions value)
        {
            return new ExecutionOptions() { ExecutionOption = value.ExecutionOption };
        }
    }
}

The implicit operator is a short cut to recreate the object of the target type from another type. In our case, we overload the implicit operator in the ExecutionOptions partial class under the BingMaps.Imagery name space. The operator automatically handles type casting from a BingMaps.Geocode.ExecutionOptions object by re-creating a local ExecutionOptions type in the class itself.

Now, we can do an implicit type cast without even noticing it:

var exOpt = new BingMaps.Geocode.ExecutionOptions { SuppressFaults = true };
var imgReq = new ImageryRequest { ExecutionOptions = exOpt };

As you can see, we can assign a BingMaps.Geocode.ExecutionOptions to a BingMaps.Imagery.ExecutionOptions without even casting it. If we overload the implicit operator for each ExecutionOptions class in the other 3 name spaces, we can simplify our code to something as below:

var exOpt = new BingMaps.Geocode.ExecutionOptions  { SuppressFaults = true };

var geoReq = new GeocodeRequest { ExecutionOptions = exOpt };
var imgReq = new ImageryRequest { ExecutionOptions = exOpt };
var rteReq = new RouteRequest { ExecutionOptions = exOpt };
var srhReq = new SearchRequest { ExecutionOptions = exOpt };

Update: “var” is used in the code samples to shorten the code for better readability. Thanks for the tip Jeff 😉

Advertisements

2 thoughts on “C#: Implicit type cast and class conflict

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s