Most of you, like me have run into the dreaded long chain of if-else statements while developing. These chain of conditional statements often make code very difficult to read and debug. While working on a recent project I discovered a new way to clean things up. I’ll first take you through the old approach
private static void Getgrade()
{
//Classic grade program
double finalGrade = 86.4;
if (finalGrade >= 95)
{
Console.WriteLine("Dan has obtained an A+, which is Outstanding");
}
else if (finalGrade >= 90 && finalGrade < 95)
{
Console.WriteLine("Dan has obtained an A-, which is Excellent");
}
else if (finalGrade >= 85 && finalGrade < 90)
{
Console.WriteLine("Dan has obtained a A, which is very good");
}
else if (finalGrade >= 70 && finalGrade < 85)
{
Console.WriteLine("Dan has obtained a B+, which is good");
}
else if (finalGrade >= 60 && finalGrade < 70)
{
Console.WriteLine("Dan has obtained a B, which is a pass");
}
else
{
Console.WriteLine("Dan has obtained an F, which is poor");
}
}

Now lets take a look at how we can improve this with our rule engine. I’ll define two classes to begin with.
public class Rule<T>
{
public Func<T, bool> Test { get; set; }
public string DisplayMessage { get; set; }
}
public class Student
{
public string Name { get; set; }
public double Grade { get; set; }
}
The first class provides us with our template to generate rules for our engine. It comprises of two properties which make use of the Func delegate.
private static void GetGradeFromRuleEngine(Student freshman)
{
var rules = new List<Rule<Student>>
{
new Rule<Student>
{
Test = e => e.Grade >= 95,
DisplayMessage =string.Format("{0} has obtained an A+, Which is Outstanding", freshman.Name)
},
new Rule<Student>
{
Test = e => e.Grade >= 90 && e.Grade < 95,
DisplayMessage =
string.Format("{0} has obtained an A-, which is Excellent", freshman.Name)
},
new Rule<Student>
{
Test = e => e.Grade >= 85 && e.Grade < 90,
DisplayMessage =
string.Format("{0} has obtained a A, which is very good", freshman.Name)
},
new Rule<Student>
{
Test = e => e.Grade >= 70 && e.Grade < 85,
DisplayMessage =
string.Format("{0} has obtained a B+, which is good", freshman.Name)
},
new Rule<Student>
{
Test = e => e.Grade >= 60 && e.Grade < 70,
DisplayMessage =
string.Format("{0} has obtained a B, which is a pass", freshman.Name)
},
new Rule<Student>
{
Test = e => e.Grade >= 60 && e.Grade < 70,
DisplayMessage =
string.Format("{0} has obtained an F, which is poor", freshman.Name)
},
};
bool isValid = rules.Any(r => r.Test(freshman));
if (isValid)
{
var validRules = rules.Where(r => r.Test(freshman));
string message = validRules.SingleOrDefault().DisplayMessage;
Console.WriteLine(message);
}
}
We then create a method which accepts a student object called GetGradeFromRuleEngine. The next thing we do is to then build our rule engine. This structure makes it very easy to modify and even add new rules to our engine. Below is how you will run this and voila.
class Program
{
static void Main(string[] args)
{
var dan = new Student()
{
Name = "Dan",
Grade = 86.4
};
GetGradeFromRuleEngine(dan);
}
}