Technically, this is a follow up to these two questions, but I have taken a radically different approach. 

1. [Everybody Loves Fibonacci](https://codereview.stackexchange.com/questions/54769/everyone-loves-fibonacci)
2. [Does everyone still love Fibonacci](https://codereview.stackexchange.com/questions/54894/does-everyone-still-love-fibonacci)

I finally allowed myself to be convinced that it *should not* be as object oriented as I wanted it to be. I opted instead to return any given \$F\_n\$ as quickly as possible. I used a Dictionary to cache previous results, always looking in the dictionary for the requested value before doing any other processing. 

So, hit me. I think I did pretty good this time around. What do you think?

**Note:** I'm avoiding the naive recursive solution because it is far slower than an iterative algorithm. 

**Fibonacci**

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

namespace Challenges
{
    class Fibonacci
    {
        private Dictionary<int, BigInteger> dictionary;

        public Fibonacci()
        {
            dictionary = new Dictionary<int, BigInteger>();
        }

        public BigInteger Calculate(int ordinalPosition)
        {
            BigInteger returnValue;
            BigInteger previous1;
            BigInteger previous2;

            //first try to get it from the dictionary
            if (dictionary.TryGetValue(ordinalPosition, out returnValue))
            {
                return returnValue;
            }

            // Fn where n < 0 doesn't make sense
            if (ordinalPosition < 0)
            {
                throw new ArgumentOutOfRangeException("OrdinalPosition", "Can't calculate Fn when n is less than zero.");
            }

            //Handle special cases of n == 0,1, or 2 (Priming the function).
            if (ordinalPosition == 0)
            {
                dictionary.Add(ordinalPosition, 0);
                return 0;
            }

            if (ordinalPosition == 1 || ordinalPosition == 2)
            {
                dictionary.Add(ordinalPosition, 1);
                return 1;
            }

            //If we already have the previous ordinalPosition, use that value to calculate the next.
            if (dictionary.TryGetValue(ordinalPosition - 1, out previous1))
            {
                dictionary.TryGetValue(ordinalPosition - 2, out previous2); //It's safe to assume if we found n-1, n-2 is there.
                returnValue = previous1 + previous2;
                dictionary.Add(ordinalPosition, returnValue);
                return returnValue;
            }

            //If we've gotten here, there's a gap between the last ordinalPosition and the one requested.
            if (dictionary.Count > 2)
            {
                //start at the next missing fibonacci number
                for (int i = dictionary.Count; i <= ordinalPosition; i++)
                {
                    dictionary.TryGetValue(dictionary.Count - 1, out previous1);
                    dictionary.TryGetValue(dictionary.Count - 2, out previous2);
                    returnValue = previous1 + previous2;
                    dictionary.Add(i, returnValue);
                }
                return returnValue;
            }

            //If all else fails, start at the beginning.
            Fibonacci fib = new Fibonacci();
            for (int i = 0; i <= ordinalPosition; i++)
            {
                dictionary.Add(i, fib.Calculate(i));
            }
            dictionary.TryGetValue(ordinalPosition, out returnValue);
            return returnValue;
        }
    }
}

```

And the largely unchanged Console program. I only updated the implementation to function, not to take advantage of the caching I added. It's just here to show that my code works. [I'm aware of some issues from a previous review](https://codereview.stackexchange.com/a/54959/41243).

```
namespace Challenges
{
    class Program
    {
         static void Main(string[] args)
        {
             Console.WriteLine("How many Fibonacci numbers should I print?");

             int input;
             if (int.TryParse(Console.ReadLine(),out input))
             {
                 WriteOkMesage();
                 WriteLotsOfFibonacci(input);   
             }
             else
             {
                 WriteNotAnIntegerMessage();
             }

            Console.WriteLine(Environment.NewLine + "Let's just pick one at random.");
            Console.WriteLine("What nth number Fibonacci would you like?");

            if (int.TryParse(Console.ReadLine(),out input))
            {
                WriteOkMesage();
                WriteAFibonacci(input);
            }
            else
            {
                WriteNotAnIntegerMessage();
            }

            Console.WriteLine("Press enter to close...");
            Console.ReadLine();
        }

        static private void WriteAFibonacci(int n)
        {
            try
            {
                Fibonacci fib = new Fibonacci();
                Console.WriteLine("The answer is: " + fib.Calculate(n));
            }
            catch(ArgumentOutOfRangeException e)
            {
                WriteErrorMessage(e);
            }
        }

        static private void WriteLotsOfFibonacci(int numberToPrint)
        {
            Fibonacci fib = new Fibonacci();
            try
            {
                for (int i = 1; i <= numberToPrint; i++)
                {
                    Console.WriteLine(fib.Calculate(i));
                }
            }
            catch (ArgumentOutOfRangeException e)
            {
                WriteErrorMessage(e);
            }
        }

        static private void WriteOkMesage()
        {
            Console.WriteLine("Okay!" + Environment.NewLine);
        }

        static private void WriteErrorMessage(Exception e)
        {
            Console.WriteLine(e.Source + " " + e.Message);
        }

        static private void WriteNotAnIntegerMessage()
        {
            Console.WriteLine("That's not an integer! I can't process that.");
        }

    }
}

```