A better switch with Lambdas in .NET, Part 3 (Adding a IComparer)

By | September 13, 2013

Well, after the previous two post, I think you have clearly got an idea on how the Lambda switcher works and even you might have already started applying them in your day to day projects. While, I have shown Equals comparison and one for StringComparison, sometimes, this couldn’t facilitate everything that we need. In this post, I would try to add a IComparer to the Switch case to have better handling of things that we need.

public static class AdvComparerSwitcher
{
public class CaseInfo
{
public T Case { get; set; }
public Action TargetAction { get; set; }
public bool IsDefault { get; set; }
}

public static void Me(T source, IComparer comparer, params CaseInfo[] cases)
{
CaseInfo defaultCase = null;
bool isTargetActionTaken = false;
foreach (var entry in cases)
{
if (entry.IsDefault)
defaultCase = entry;

if (!entry.IsDefault && comparer != null && comparer.Compare(source, entry.Case) == 0)
{
entry.TargetAction(source);
isTargetActionTaken = true;
break;
}
}
if (!isTargetActionTaken && defaultCase != null)
defaultCase.TargetAction(source);
}

public static CaseInfo Case(T source, Action action)
{
return new CaseInfo { TargetAction = x => action(), Case = source };
}

public static CaseInfo Default(Action action)
{
return new CaseInfo { TargetAction = x => action(), IsDefault = true };
}
}

Here, the above lambda requires an IComparer to it to compare between types. The IComparer interface gives you some more flexibility to determine how much the differences between the two places of an object. Here in each cases, it determines the integer by calling the method Comparer outside its scope by inverting its control and henceforth determining whether the compare gives an equality. Depending on that it can go ahead and call the TargetAction.

To call this, let us first implement an IComparer for a Type.

public class MyType
{
public string Name { get; set; }
public int Age { get; set; }
}
public class MyTypeComparer : IComparer
{
public int Compare(MyType x, MyType y)
{
if (x.Name.Equals(y.Name) && x.Age.Equals(y.Age))
return 0;
else
{
// We can check and return the value we want, for simplicity we return -1 for inequality
return -1;
}
}
}

In the above code, we have created a new type called MyType and also added an IComparer which compares two MyType objects and returns integer value such that when both the properties are equal it returns 0 otherwise it returns -1. Now our case will invert the control and call the Compare of the IComparer while determining the equality. Let us try to implement Switcher with Comparer.

static void Main(string[] args)
{
MyType strType = new MyType { Name = "Abhishek", Age = 30 };
AdvComparerSwitcher.Me(strType,
new MyTypeComparer(),
new AdvComparerSwitcher.CaseInfo
{
Case = new MyType { Name = "Abhishek", Age = 30 },
TargetAction = e =>
{
Console.WriteLine("Abhishek:" + e.Name);
}
},
new AdvComparerSwitcher.CaseInfo
{
Case = new MyType { Name = "Abhijit", Age = 20 },
TargetAction = e =>
{
Console.WriteLine("Abhijit:" + e.Name);
}
},
new AdvComparerSwitcher.CaseInfo
{
Case = new MyType { Name = "Anoop", Age = 35 },
TargetAction = e =>
{
Console.WriteLine("Anoop:" + e.Name);
}
},
new AdvComparerSwitcher.CaseInfo
{
IsDefault = true,
TargetAction = e =>
{
Console.WriteLine("Default");
}
});

Console.ReadKey(true);
}

Here in the call above, the first case will get executed as both the properties are same and will print Abhishek : Abhishek. But the catch is that, it actually uses MyTypeComparer to determine the actual comparison. So when the AdvComparerSwitcher is called, it goes ahead and calls the Comparer method of the MyTypeComparer and determines the equality. If any of the switches does not execute, it will call the Default switch.

Conclusion

As we progress further, we will add more new switch cases, stay tune to the blog to get more of these.

I hope you like this post.

Happy programming !