Custom Explicit and Implicit Operators in C#

I recently had a friend ask me about my use of implicit operators.  I’ve been using them for a while now, but don’t think they’ve gained much traction for some reason, as I rarely come across code where they’ve been implemented.

Using implicit or explicit operators at their base implementation is quite easy, there’s a few simple rules to follow when implementing them:

  • The operator must be enclosed in the class or partial class that it converts
  • It must accept only 1 parameter

There’s a few other rules, but those are the two important ones to follow when getting started.

Implicit Operator

public class CustomerDTO
   {
       public static implicit operator CustomerDTO(Customer entityObject)
       {
           
       }
   }

Pretty easy to implement, and you implement explicit operators the same way.  The major difference being the required explicit call on an explicit operator such as:

CustomerDTO.ToCustomer()

For this example, I’ve created a very small model of a customer object, with addresses.  This model is not connected to a database, and utilizes the model designer of the Entity Framework 4.0. 

EF4 Model

 

I’ve also wired up to POCO (Plain old CLR Objects) objects, as DTO’s (data transfer objects).  The scope of this entry is not to describe why you’d use POCO or transfer objects, but if you’re using them, and doing manual conversions this will save you a LOT of headache. :)

public class CustomerDTO
   {
       int id { get; set; }
       string name { get; set; }
       string taxid { get; set; }
       Status active { get; set; }
       IEnumerable<AddressDTO> addresses { get; set; }
   }
 
   public enum Status
   {
       Inactive, //=0
       Active //=1
   }

public class AddressDTO
    {
        int id { get; set; }
        string address1 { get; set; }
        string city { get; set; }
        string state { get; set; }
        string zip { get; set; }
        int Customerid { get; set; }
    }

 

Once we have our model in place, and our POCO objects created, we can get into the meat of the operators we want to implement. 

Lets start with the CustomerDTO operator:

public static implicit operator CustomerDTO(Customer entityObject)
        {
            return new CustomerDTO
            {
                taxid = entityObject.TaxID,
                name = entityObject.Name,
                id = entityObject.Id,
                addresses = entityObject.Addresses,
                active = (Status)Enum.Parse(typeof(Status), entityObject.Active)
            };
        }

You’ll notice that when you implement this code, you receive this error:

image

This is exactaly where implicit operators come in!  When we go and define the implicit operator for the Address, we’ll solve our problem here:

public static implicit operator AddressDTO(Address entityAddress)
       {
           return new AddressDTO
           {
               id = entityAddress.Id,
               address1 = entityAddress.Address1,
               city = entityAddress.City,
               state = entityAddress.State,
               zip = entityAddress.Zip,
               Customerid = entityAddress.CustomerId
           };
       }

 

The finished CustomerDTO implicit operator:

public static implicit operator CustomerDTO(Customer entityObject)
        {
            CustomerDTO returnObject = new CustomerDTO()
            {
                taxid = entityObject.TaxID,
                name = entityObject.Name,
                id = entityObject.Id,
                active = (Status)Enum.Parse(typeof(Status), entityObject.Active)
            };
 
            // Do this longhand for visibility
            // Without the implicit operator for AddressDTO we could not use the ().Add(e) without an implicit cast error
            entityObject.Addresses.ToList().ForEach(e => returnObject.addresses.ToList().Add(e));
 
 
            return returnObject;
        }

Now all that would be left, would be to extend the partial classes of our Entity Framework objects, such as the Customer and Address to return DTO objects

 

Now, anywhere in our business logic we can use implicit converstion such as

AddressDTO = Address

Address = AddressDTO

Customer = CustomerDTO

CustomerDTO = Customer

 

Hope that makes life easier --- 

Code happy!

Published Thursday, January 7, 2010 9:09 AM by Freakyuno

Comments

# re: Custom Explicit and Implicit Operators in C#

Thursday, January 7, 2010 11:30 AM by paul.vencill

Very cool!  You didn't explicitly (ha!) say it in your article, but this looks like a new 4.0 feature, am I right?

# re: Custom Explicit and Implicit Operators in C#

Thursday, January 7, 2010 11:33 AM by Freakyuno

@Paul.Vencill

Hi Paul,

It's not specifically a .NET 4.0 feature, but LINQ syntax and the EF4.0 framework makes them super usefull. :)

# re: Custom Explicit and Implicit Operators in C#

Thursday, January 7, 2010 11:46 AM by Ramon Smits

Please don't do this, this is a very bad practise! Do not use implicit overloading for such tasks. Even explicit overloading is not recommended. Just because the language supports this does not mean you should use it for such tasks.

This way you extend the most simple classes with business logic mapping to/from other data.

I also recommend to have object builds responsible for creating objects as to have single point of responsibility when you extend an object with for example mandatory data members.

# re: Custom Explicit and Implicit Operators in C#

Thursday, January 7, 2010 12:06 PM by Freakyuno

@Ramon Smits

Hi Ramon,

The entity object / data object example above, is just used as a simple example to demonstrate the use of implicit operators.

It's not an implicit operator overload, it's a custom implicit operator mapping from a non native .NET object to another.  Implicit and Explicit operators aren't a bad thing.

As always, the architecture of your application should be closely examined, and custom operators should only be implemented where they are appropriate.

As an alternative, extension methods could be used, but that then relies on calling the extension method inline to each implementation.

The issue in many architectures that I see, especially in large disseperate organizations with large development teams is, the data layer, and the business layer are not typically written in conjunction with each other.

The use of custom operators enables an architecture where the mapping from 1 object is defined and controlled.  The other side of that scenario is your business developer doing mutex operations inside their business class which I see as a worse alternative.

# re: Custom Explicit and Implicit Operators in C#

Friday, January 8, 2010 7:52 AM by Derek Fowler

I quite like the way you could enumerate over a collection of Customer objects as CustomerDTO objects e.g.

List<Customer> customers;

foreach(CustomerDTO dto in customers)

{

// do stuff

}

My only concern is that it would potentially be doing a lot of work behind the scenes that you aren't necessarily aware of because you aren't calling any methods.

# re: Custom Explicit and Implicit Operators in C#

Friday, January 8, 2010 1:22 PM by sohan

I liked the post as an example of implicit operator implementation. But I don't think its a good idea to have separate classes for DTO and DL. This is because you are duplicating the code and it runs the risk of all issues that comes when you violate Don't Repeat Yourself principle.

Also, as an example, I think the MSDN one is a good one. You can add a link to the MSDN page.

# re: Custom Explicit and Implicit Operators in C#

Friday, January 8, 2010 5:25 PM by Freakyuno

@Sohan

The seperation between an Entity Framework model, and POCO objects is a well defined and well used model.  I'm not a huge fan of creating POCO objects myself, because of the time involved, but sometimes there's no way around it.

What you're specifically refering to I believe is "Change Tracking" across your object mappings, in which case you're correct, this becomes a difficult issue.

You may want to read this article on POCO objects and the Repository Pattern for Entity Frameworks:

blogs.msdn.com/.../poco-in-the-entity-framework-part-1-the-experience.aspx

Bryan