Hello Devz,

Sometimes it is hard to take a decision. And to represent the possibilities of complex decisions, it is usefull to use a Decision Tree. Instead of having all the parameters at once, you can simply take small decision at a time and then go further. In this simple tutorial we will show an example of a decision tree that will check if a client can receive a loan from a bank.

Let’s first have a look at our client to evaluate:

var john = new Client
{
    Name = "John Doe",
    IsLoanNeeded = true,
    Income = 45000,
    YearsInJob = 4,
    UsesCreditCard = true,
    CriminalRecord = false
};

Based on our Client model:

public class Client
{
    public string Name { get; set; }
    public bool IsLoanNeeded { get; set; }
    public decimal Income { get; set; }
    public int YearsInJob { get; set; }
    public bool UsesCreditCard { get; set; }
    public bool CriminalRecord { get; set; }
}

Now, the goal is to take a decision. So let’s create some Decision classes:

public abstract class Decision
{
    public abstract void Evaluate(Client client);
}

Our Decision class will have to evaluate a Client. This evaluation will be based on a DecisionQuery (the question) and a DecisionResult (the response).

public class DecisionQuery : Decision
{
    public string Title { get; set; }
    public Decision Positive { get; set; }
    public Decision Negative { get; set; }
    public Func<Client, bool> Test { get; set; }

    public override void Evaluate(Client client)
    {
        bool result = this.Test(client);
        string resultAsString = result ? "yes" : "no";

        Console.WriteLine($"\t- {this.Title}? {resultAsString}");

        if (result) this.Positive.Evaluate(client);
        else this.Negative.Evaluate(client);
    }
}

The Test Func will simply verify if the condition is met (for example: is our client earning enough money to be able to refund his loan). Depending on the result of this Test, we will take an orientation: Positive or Negative. Both of them are Decisions as well.

Here is the DecisionResult class, which will contain the final result of our decision tree:

public class DecisionResult : Decision
{
    public bool Result { get; set; }
    public override void Evaluate(Client client)
    {
        Console.WriteLine("\r\nOFFER A LOAN: {0}", Result ? "YES" : "NO");
    }
}

Now, let’s create our tree! We will start with one simple question… Does our client need a loan? If yes, then check if our client have a criminal record. If no, then check how much money he earns. If he earns enough money to refund the loan, then check if he have enough exeprience in his job (not a newbie that will maybe lose his job tomorrow). If yes, then check if he uses his creditcard (why not…).

By this unreadable text, you will understand the real value of a decision tree.

private static DecisionQuery MainDecisionTree()
{
    //Decision 4
    var creditBranch = new DecisionQuery
    {
        Title = "Use credit card",
        Test = (client) => client.UsesCreditCard,
        Positive = new DecisionResult { Result = true },
        Negative = new DecisionResult { Result = false }
    };

    //Decision 3
    var experienceBranch = new DecisionQuery
    {
        Title = "Have more than 3 years experience",
        Test = (client) => client.YearsInJob > 3,
        Positive = creditBranch,
        Negative = new DecisionResult { Result = false }
    };


    //Decision 2
    var moneyBranch = new DecisionQuery
    {
        Title = "Earn more than 40k per year",
        Test = (client) => client.Income > 40000,
        Positive = experienceBranch,
        Negative = new DecisionResult { Result = false }
    };

    //Decision 1
    var criminalBranch = new DecisionQuery
    {
        Title = "Have a criminal record",
        Test = (client) => client.CriminalRecord,
        Positive = new DecisionResult { Result = false },
        Negative = moneyBranch
    };

    //Decision 0
    var trunk = new DecisionQuery
    {
        Title = "Want a loan",
        Test = (client) => client.IsLoanNeeded,
        Positive = criminalBranch,
        Negative = new DecisionResult { Result = false }
    };

    return trunk;
}

Last but not least, our Main method. It will receive the decision tree built just above, create our client, and then evaluate it.

private static void Main(string[] args)
{
    var trunk = MainDecisionTree();

    var john = new Client
    {
        Name = "John Doe",
        IsLoanNeeded = true,
        Income = 45000,
        YearsInJob = 4,
        UsesCreditCard = true,
        CriminalRecord = false
    };

    trunk.Evaluate(john);

    Console.WriteLine("Press any key...");
    Console.ReadKey();
}

And here is the final result:

C# - decision tree - simple example

C# – decision tree – simple example

Our dear mister John Doe will receive his loan.

Happy decisions!  😉