As it happens, your mistake has nothing to do with recursion. You're problem is, that you call a method twice, instead of saving the value of it. You wouldn't even realize this, if you wouldn't print the result. As @JLK pointed out, you call it twice in this snippet:
Console.WriteLine("{0} * {1}", n, Factorial(n - 1));
return n * Factorial(n - 1);
Let's step through the code, so that we can understand the output:
Factorial (3);
-> output 3 * {Factorial (2)} // 3 * 2 (4)
-> output 2 * {Factorial (1)} // 2 * 1 (2)
-> output 1 * {Factorial (0)} // 1 * 1 (1)
<- 1
Factorial (0)
<- 2
Factorial (1)
-> output 1 * {Factorial (0)} // 1 * 1 (3)
<- 1
Factorial (0)
<- 1
<- 1
Factorial (2)
-> output 2 * {Factorial (1)} // 2 * 1 (6)
-> output 1 * {Factorial (0)} // 1 * 1 (5)
<- 1
Factorial (0)
<- 1
Factorial (1)
-> output 1 * {Factorial (0)} // 1 * 1 (7)
<- 1
Factorial (0)
<- 1
<- 2
This might be a bit confusing, but that's normal for recursion. So basically all you have to do is to change the code snippet a little bit:
var factorial = Factorial (n - 1);
Console.WriteLine("{0} * {1}", n, factorial);
return n * factorial;
The output then is:
1 * 1
2 * 1
3 * 2
6
If you want to learn more about recursion, I'd suggest this site. It isn't about C#, but it's a great site to learn recursion in general. If you want to do much in recursion, I wouldn't suggest C# anyway, as it is an imperative language. For recursion functional languages are better suited. If you still want to keep close to C#, or at least use the .Net framework, I'd suggest to use F#, which is the functional equivalent of C#.
The main problem with C# and recursion is, that C# doesn't support Tail recursion. This can easily result in StackOverflows, when you do deeper recursive calls (like for example an infinite recursive loop). This is because everytime you call a function, the code address from which you called the function is pushed onto the stack. So everytime you do a recursive call, the code adddress is pushed to the stack. So if you have for example this function:
void rec () => rec();
You get a StackOverflow in less than a second in C# by calling it. Tail recursion however solves this problem at least partially: It doesn't push the code address of the caller if the recursive call was the last execution in a function. So in F# this runs forever:
let rec r () =
r ()
r ()
(I won't go deeper into F# syntax, there are enough tutorials online). I said it solves the problem only partially, because this:
let rec r () =
r ()
()
r ()
results in a StackOverflow once again. I'm not aware of any programming language, where this isn't the case, so you'll just have to get used to using tail recursion.
You can read more about functional / recursive languages in this post.