Static implicit operator

C#OperatorsImplicit Conversion

C# Problem Overview


I recently found this code:

 public static implicit operator XElement(XmlBase xmlBase)
 {
     return xmlBase.Xml;
 }

What does static implicit operator mean?

C# Solutions


Solution 1 - C#

This is a conversion operator. It means that you can write this code:

XmlBase myBase = new XmlBase();
XElement myElement = myBase;

And the compiler won't complain! At runtime, the conversion operator will be executed - passing myBase in as the argument, and returning a valid XElement as the result.

It's a way for you as a developer to tell the compiler:

>"even though these look like two totally unrelated types, there is actually a way to convert from one to the other; just let me handle the logic for how to do it."

Solution 2 - C#

Such an implicit operator means you can convert XmlBase to XElement implicitly.

XmlBase xmlBase = WhatEverGetTheXmlBase();
XElement xelement = xmlBase;   
//no explicit convert here like: XElement xelement = (XElement)xmlBase;

Solution 3 - C#

Another interesting usage is (which Unity did to check if an object (and therefore an instance of MonoBehavior) is null):

public static implicit operator bool (CustomClass c)
{
    return c != null;
}

Note that the code has to be inside the class (CustomClass in this case). That way you can do something like this:

void Method ()
{
    CustomClass c1 = null;
    CustomClass c2 = new CustomClass ();

    bool b1 = c1; // is false
    bool b2 = c2; // is true

    if (!c1 && c2)
    {
        // Do stuff
    }
}

Obviously the most notorious use might be using it to convert one of your classes to another of your classes. But using them with basic types is worth a consideration as well... and I see it mentioned quite rarely.

Solution 4 - C#

It's an implicit conversion operator (as opposed to an Explicit operator, which requires the (type) conversion syntax)

Solution 5 - C#

My two cents.

This is useful in Unit testing an immutable entity to be used with Builder Pattern.

Say you have Employee domain object defined in an immutable way. We do this typically when want to adhere to DDD style.

public class Employee 
{ 
  public Employee(int id, string firstname, string lastname, DateTime birthdate, string street) 
  { 
    this.ID = id; 
    this.FirstName = firstname; 
    this.LastName = lastname; 
    this.BirthDate = birthdate; 
    this.Street = street; 
  } 

  public int ID { get; private set; } 
  public string FirstName { get; private set; } 
  public string LastName { get; private set; }
  public DateTime BirthDate { get; private set; } 
  public string Street { get; private set; } 

  public string getFullName() 
  { 
    return this.FirstName + " " + this.LastName; 
  } 

  public int getAge() 
  { 
    DateTime today = DateTime.Today;
    int age = today.Year - BirthDate.Year;
    
    if (BirthDate > today.AddYears(-age))
      age--;

    return age; 
  } 
}

Now you can have an employee builder like the following(inside of the test project). Notice in the end, we have this implicit operator.

public class EmployeeBuilder
{ 
  private int id = 1; 
  private string firstname = "first"; 
  private string lastname = "last"; 
  private DateTime birthdate = DateTime.Today; 
  private string street = "street"; 
  public Employee Build() 
  { 
    return new Employee(id, firstname, lastname, birthdate, street); 
  } 
  public EmployeeBuilder WithFirstName(string firstname) 
  { 
    this.firstname = firstname; 
    return this; 
  } 
  public EmployeeBuilder WithLastName(string lastname) 
  { 
    this.lastname = lastname; 
    return this; 
  } 
  public EmployeeBuilder WithBirthDate(DateTime birthdate) 
  { 
    this.birthdate = birthdate; 
    return this; 
  } 
  public EmployeeBuilder WithStreet(string street) 
  { 
    this.street = street; 
    return this; 
  } 
  public static implicit operator Employee(EmployeeBuilder instance) 
  { 
    return instance.Build(); 
  } 
}

Now you can have a employee test class like the following.

public class EmployeeTest
{
  [Test]
  public void GetFullNameReturnsCombination()
  { 
    // Arrange
    Employee emp = new EmployeeBuilder().WithFirstName("Vivek").WithLastName("Koppula"); 
    // Act
    string fullname = emp.getFullName(); 
    // Assert
    Assert.That(fullname, Is.EqualTo("Vivek Koppula")); 
  } 

  [Test] 
  public void GetAgeReturnsCorrectValue() { 
  // Arrange
  Employee emp = new EmployeeBuilder().WithBirthDate(new DateTime(1983, 1,1)); 
  // Act
  int age = emp.getAge(); 
  // Assert
  Assert.That(age, Is.EqualTo(DateTime.Today.Year - 1983)); 
  } 
}

This makes writing unit tests easier by enabling us to construct the employee just with required parameters.

For example in the first test, we are only concerned with first name and last name. So for the first case, we don't have to be bothered by age and street.

Similarly for the second case, we are concerned with age and nothing else.

Article References.

  1. flexible-and-expressive-unit-tests-with-the-builder-pattern
  2. improve-tests-with-the-builder-pattern-for-test-data

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBartView Question on Stackoverflow
Solution 1 - C#Rex MView Answer on Stackoverflow
Solution 2 - C#Cheng ChenView Answer on Stackoverflow
Solution 3 - C#BattleView Answer on Stackoverflow
Solution 4 - C#Andrew BarberView Answer on Stackoverflow
Solution 5 - C#VivekDevView Answer on Stackoverflow