# Mapping without the switch command

21. July 2013 16:57

In a project I had to map a lot of external codes and values to our codes and values. This results in methods with switch statements:

```private int GetInternalCode(string externalCode)
{
var result = 0;
switch (externalCode)
{
case "A":
result = 0;
break;
case "B":
result = 2;
break;
case "C":
result = 5;
break;
default:
result = 6;
break;
}

return result;
}```

This is a lot of plumbing code so I decided to write some mapping extensions. The above code can now be written likke this.

```private int GetInternalCode(string externalCode)
{
return externalCode
.Map("A", 0)
.Map("B", 2)
.Map("C", 5)
.Else(6);
}```

This a lot easier to write and maintain. The mapping extensions are also more flexible. It can uses functions to select the right value.

```private int GetExternalCode(int internalCode)
{
return internalCode
.Map(0, -1)
.Map(IsEven, 1)
.Map(x => x > 100, 2)
.Map(51, 3)
.Else(4);
}```

And it uses functions to define the result value:

```private int GetExternalCode(int internalCode)
{
return internalCode
.Map(0, -1)
.Map(IsEven, GetDoubleValue)
.Map(x => x > 100, -2)
.Else(x => x + 2);
}

private int GetDoubleValue(int value)
{
return value * 2;
}```

With the Visual Basic Select Case statement, you can use ranges and lists. With 2 handy extra extensions, you can do the same.

The extra extensions class:

```using System;
using System.Collections.Generic;
using System.Linq;

namespace Blog.Mapping
{
public static class OtherExtensions
{
public static bool IsInRange<T>(this T source, T minimum, T maximum) where T : IComparable<T>
{
return source.CompareTo(minimum) >= 0 && source.CompareTo(maximum) <= 0;
}

public static bool IsIn<T>(this T source, params T[] values)
{
return values.Contains(source);
}
}
}```

New mapping options:

```private int GetExternalCode(int internalCode)
{
return internalCode
.Map(x => x.IsIn(1, 3, 8, 12, 13), 1)
.Map(x => x.IsIn(20,25,30), 2)
.Map(x => x.IsInRange(30, 50), 3)
.Else(4);
}```

If an "else value" is prohibited, you can easily throw an exception (or something else like some logging code).

```private int GetInternalCode(string externalCode)
{
return externalCode
.Map("A", 0)
.Map("B", 2)
.Map("C", 5)
.ElseDo(x =>
{
throw new ArgumentException("The following value can not be mapped:" + x, "externalCode");
});
}```

Below you find the code of the 2 classes that make this way of mapping possible:

1: A normal class

```using System;
using System.Collections.Generic;

namespace Blog.Mapping
{
public class MapResult<TValue, TResult>
{
private TValue OriginalValue { get; set; }
public TResult Result { get; private set; }
private bool MatchedPreviously { get; set; }

internal MapResult(TValue value, TResult result = default(TResult), bool matchedPreviously = false)
{
OriginalValue = value;
Result = result;
MatchedPreviously = matchedPreviously;
}

public MapResult<TValue, TResult> Map(TValue ifValue, TResult thenValue)
{
return Map(x => x.Equals(ifValue), x => thenValue);
}

public MapResult<TValue, TResult> Map(TValue ifValue, Func<TValue, TResult> thenFunc)
{
return Map(x => x.Equals(ifValue), thenFunc);
}

public MapResult<TValue, TResult> Map(Func<TValue, bool> ifFunc, TResult thenValue)
{
return Map(ifFunc, x => thenValue);
}

public MapResult<TValue, TResult> Map(Func<TValue, bool> ifFunc, Func<TValue, TResult> thenFunc)
{
if (MatchedPreviously || !ifFunc(OriginalValue))
{
return this;
}
var result = new MapResult<TValue, TResult>(OriginalValue, thenFunc(OriginalValue), true);
return result;
}

public TResult Else(TResult elseValue)
{
return Else(x => elseValue);
}

public TResult Else(Func<TValue, TResult> elseFunc)
{
if (MatchedPreviously)
{
return Result;
}
var result =  elseFunc(OriginalValue);
return result;
}

public TResult ElseDo(Action<TValue> doThis)
{
if (MatchedPreviously)
{
return Result;
}
doThis(OriginalValue);
return Result;
}

public static implicit operator TResult(MapResult<TValue, TResult> value)
{
return value.Result;
}
}
}```

2: And the extension class

```using System;

namespace Blog.Mapping
{
public static class MapExtensions
{
public static MapResult<TValue, TResult> Map<TValue, TResult>(this TValue originalValue, TValue ifValue, TResult thenValue)
{
return new MapResult<TValue, TResult>(originalValue).Map(ifValue, thenValue);
}

public static MapResult<TValue, TResult> Map<TValue, TResult>(this TValue originalValue, Func<TValue, bool> ifFunc, TResult thenValue)
{
return new MapResult<TValue, TResult>(originalValue).Map(ifFunc, thenValue);
}

public static MapResult<TValue, TResult> Map<TValue, TResult>(this TValue originalValue, TValue ifValue, Func<TValue, TResult> thenFunc)
{
return new MapResult<TValue, TResult>(originalValue).Map(ifValue, thenFunc);
}

public static MapResult<TValue, TResult> Map<TValue, TResult>(this TValue originalValue, Func<TValue, bool> ifFunc, Func<TValue, TResult> thenFunc)
{
return new MapResult<TValue, TResult>(originalValue).Map(ifFunc, thenFunc);
}
}
}```

Tags:

### Add comment

• Comment
• Preview

#### About the author

I am a software architect at Roxit and also a C# Developer. My main interests in the area of ​​C# are LINQ and generics

Visit my personal homepage (Dutch) for more info about me.