5! is 5 x 4 x 3 x 2 x 1 = 120. A factorial program in C# starts a long at 1 and multiplies it by every number from 2 to n. For 0 and 1 the loop never runs, so you get 1.
static long Factorial(int n)
{
long result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
}
In this tutorial, I’ll cover the factorial program in C# the way interviewers and CS courses ask for it: for and while loops, recursion, LINQ, overflow in int and long, BigInteger, negative input and a lookup table.
Factorial Program in C# Using a for Loop
Here’s the full .NET 10 file-based app. dotnet run ForLoop.cs runs it without a project:
Console.WriteLine($"5! = {Factorial(5)}");
Console.WriteLine($"10! = {Factorial(10)}");
Console.WriteLine($"0! = {Factorial(0)}");
try { Factorial(-3); }
catch (ArgumentOutOfRangeException ex) { Console.WriteLine(ex.Message); }
static long Factorial(int n)
{
ArgumentOutOfRangeException.ThrowIfNegative(n);
long result = 1; // 0! and 1! stay 1
for (int i = 2; i <= n; i++)
result *= i;
return result;
}
Output:
5! = 120
10! = 3628800
0! = 1
n ('-3') must be a non-negative value. (Parameter 'n')
Actual value was -3.

The loop starts at 2 because multiplying by 1 changes nothing. If the counter syntax is new to you, see the for loop in C#.
The last line is the negative-number guard. ArgumentOutOfRangeException.ThrowIfNegative(n) (.NET 8+) writes that message for you; without it, -3 quietly returns 1.
Factorial of a Number with a while Loop
Some assignments want a while loop. This one counts n down instead:
Console.WriteLine($"8! = {Factorial(8)}");
static long Factorial(int n)
{
ArgumentOutOfRangeException.ThrowIfNegative(n);
long result = 1;
while (n > 1)
{
result *= n;
n--; // count down instead of up
}
return result;
}
Output:
8! = 40320
It does the same multiplications in reverse. The while loop in C# post covers when each loop fits better.
Recursive Factorial in C#
Interviewers usually ask for recursion next. The method calls itself with n – 1 until the base case, 0! = 1:
foreach (int n in new[] { 0, 5, 20 })
Console.WriteLine($"{n,2}! = {Factorial(n)}");
static long Factorial(int n)
{
ArgumentOutOfRangeException.ThrowIfNegative(n);
if (n == 0) return 1; // base case
return n * Factorial(n - 1); // n! = n x (n - 1)!
}
Output:
0! = 1
5! = 120
20! = 2432902008176640000

It reads exactly like the math, n! = n x (n – 1)!. If methods that return values are still fuzzy, start with functions in C#.
One catch: every call adds a stack frame, and a very deep recursion can crash the process with a StackOverflowException you can’t catch. That’s why the loop is the safer default.
Factorial with LINQ Aggregate in C#
If you like one-liners, Enumerable.Range plus Aggregate multiplies the sequence 1..n into a seed of 1:
foreach (int n in new[] { 0, 7, 15 })
{
long f = Enumerable.Range(1, n).Aggregate(1L, (acc, x) => acc * x);
Console.WriteLine($"{n,2}! = {f}");
}
Output:
0! = 1
7! = 5040
15! = 1307674368000
The 1L seed makes the accumulator a long, and it’s what 0! returns, because Range(1, 0) is empty.
Why Does My Factorial Program Print a Wrong or Negative Number?
Because factorials outgrow int and long fast. I ran the same loop with three types side by side:
using System.Numerics;
Console.WriteLine($"{"n",2} | {"int",11} | {"long",20} | BigInteger");
foreach (int n in new[] { 12, 13, 20, 21 })
{
int i = 1; long l = 1; BigInteger b = 1;
for (int k = 2; k <= n; k++)
{
i *= k; l *= k; b *= k; // same math, three types
}
Console.WriteLine($"{n,2} | {i,11} | {l,20} | {b}");
}
Output:
n | int | long | BigInteger
12 | 479001600 | 479001600 | 479001600
13 | 1932053504 | 6227020800 | 6227020800
20 | -2102132736 | 2432902008176640000 | 2432902008176640000
21 | -1195114496 | -4249290049419214848 | 51090942171709440000

Look at 13!. int prints 1,932,053,504 instead of 6,227,020,800, a wrong value that looks fine. long lasts until 21!, then goes negative.
Integer math runs unchecked by default, so the high bits are silently dropped.
Catch Factorial Overflow with checked and decimal
When a wrong answer is worse than a crash, wrap the multiply in checked. decimal always throws on overflow:
foreach (int n in new[] { 20, 21 }) Show(() => $"checked long {n}! = {CheckedFactorial(n)}");
foreach (int n in new[] { 27, 28 }) Show(() => $"decimal {n}! = {DecimalFactorial(n)}");
static void Show(Func<string> calc)
{
try { Console.WriteLine(calc()); }
catch (OverflowException ex) { Console.WriteLine(ex.Message); }
}
static long CheckedFactorial(int n)
{
long result = 1;
for (int i = 2; i <= n; i++)
result = checked(result * i);
return result;
}
static decimal DecimalFactorial(int n)
{
decimal result = 1;
for (int i = 2; i <= n; i++)
result *= i;
return result;
}
Output:
checked long 20! = 2432902008176640000
Arithmetic operation resulted in an overflow.
decimal 27! = 10888869450418352160768000000
Value was either too large or too small for a Decimal.
checked keeps long’s 20! limit but throws OverflowException at 21!, which you can handle with try-catch in C#. decimal stretches the range to 27!, then throws at 28!.
Factorial of 100 in C# with BigInteger
For anything bigger, use System.Numerics.BigInteger. It has no fixed upper limit:
using System.Numerics;
string digits = Factorial(100).ToString();
Console.WriteLine($"100! has {digits.Length} digits");
Console.WriteLine($"Starts with: {digits[..20]}...");
Console.WriteLine($"Trailing zeros: {digits.Length - digits.TrimEnd('0').Length}");
static BigInteger Factorial(int n)
{
ArgumentOutOfRangeException.ThrowIfNegative(n);
BigInteger result = BigInteger.One;
for (int i = 2; i <= n; i++)
result *= i;
return result;
}
Output:
100! has 158 digits
Starts with: 93326215443944152681...
Trailing zeros: 24

No built-in integer type comes close to 158 digits. BigInteger is slower than long, but it’s also what you’d use for big terms in the Fibonacci series program.
Fast Repeated Calls with a Factorial Lookup Table
If your code calls factorial over and over, say in a combinations formula, don’t recompute it. Only 0! to 20! fit in a long, so I build them once:
Console.WriteLine($"FactorialTable.Get(6) = {FactorialTable.Get(6)}");
Console.WriteLine($"FactorialTable.Get(20) = {FactorialTable.Get(20)}");
try { FactorialTable.Get(21); }
catch (ArgumentOutOfRangeException ex) { Console.WriteLine(ex.Message); }
static class FactorialTable
{
static readonly long[] Table = new long[21]; // 0! to 20!
static FactorialTable() // runs once
{
Table[0] = 1;
for (int i = 1; i < Table.Length; i++) Table[i] = Table[i - 1] * i;
}
public static long Get(int n)
{
ArgumentOutOfRangeException.ThrowIfNegative(n);
ArgumentOutOfRangeException.ThrowIfGreaterThan(n, 20);
return Table[n];
}
}
Output:
FactorialTable.Get(6) = 720
FactorialTable.Get(20) = 2432902008176640000
n ('21') must be less than or equal to '20'. (Parameter 'n')
Actual value was 21.

Each call is now an array read. Past 20!, cache BigInteger results in a Dictionary in C# keyed by n.
Which Factorial Method in C# Should You Use?
| You need | Use | Range from my runs |
|---|---|---|
| A simple answer for class | for or while loop with long | 0! to 20! |
| The interview recursion question | Recursive method | 0! to 20! |
| An error instead of a wrong value | checked long or decimal | throws at 21! / 28! |
| Big results like 100! | BigInteger loop | 158 digits |
| Many calls in a loop | Lookup table | array read per call |
Factorial sits next to the prime number program in C# in most C# interview questions for freshers.
Still warming up for coding rounds? Try these next:
Frequently Asked Questions
How do I find the factorial of a number entered by the user in C#?
Read it with Console.ReadLine(), convert it with int.TryParse(input, out int n), and pass n to Factorial. TryParse returns false instead of throwing on bad text.
Why is 0! equal to 1?
0! is the empty product, which is 1, and it keeps n! = n x (n – 1)! true for 1!. In code, the loop doesn’t run, so the starting value of 1 comes back.
What is the largest factorial a long can hold in C#?
20!, which is 2,432,902,008,176,640,000. 21! is bigger than long.MaxValue, so it wraps to a negative number unless you use checked, decimal (up to 27!) or BigInteger.
Does .NET have a built-in factorial method?
No. There’s no Math.Factorial in .NET 10, so you write the loop yourself. For large values, use the loop with BigInteger.
Is recursion or a loop better for factorial in C#?
A loop: no extra stack frames and easier to debug. Recursion is fine for interviews and small n.
Bijay Kumar is a renowned software engineer, accomplished author, and distinguished Microsoft Most Valuable Professional (MVP) specializing in SharePoint. With a rich professional background spanning over 15 years, Bijay has established himself as an authority in the field of information technology. He possesses unparalleled expertise in multiple programming languages and technologies such as ASP.NET, ASP.NET MVC, C#.NET, and SharePoint, which has enabled him to develop innovative and cutting-edge solutions for clients across the globe. Read more…