C#
Type checking
number detection
programming
.NET

C - how to determine whether a Type is a number

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In C#, determining whether a Type is numeric is trickier than it first looks because there is no single built-in IsNumeric property on System.Type. The practical solution depends on context. For runtime reflection, a TypeCode-based check or an explicit whitelist of numeric types is usually the clearest answer.

Why IsPrimitive Is Not Enough

A first attempt is often:

csharp
type.IsPrimitive

That is not sufficient because bool and char are primitive too, and decimal is numeric but not primitive.

So this is wrong for numeric detection:

csharp
// type.IsPrimitive

It answers a different question.

Use TypeCode

One common runtime approach is to switch on Type.GetTypeCode.

csharp
1using System;
2
3public static class TypeHelpers
4{
5    public static bool IsNumericType(Type type)
6    {
7        type = Nullable.GetUnderlyingType(type) ?? type;
8
9        switch (Type.GetTypeCode(type))
10        {
11            case TypeCode.Byte:
12            case TypeCode.SByte:
13            case TypeCode.UInt16:
14            case TypeCode.UInt32:
15            case TypeCode.UInt64:
16            case TypeCode.Int16:
17            case TypeCode.Int32:
18            case TypeCode.Int64:
19            case TypeCode.Decimal:
20            case TypeCode.Double:
21            case TypeCode.Single:
22                return true;
23            default:
24                return false;
25        }
26    }
27}
28
29Console.WriteLine(TypeHelpers.IsNumericType(typeof(int)));
30Console.WriteLine(TypeHelpers.IsNumericType(typeof(string)));
31Console.WriteLine(TypeHelpers.IsNumericType(typeof(decimal?)));

This is a good general-purpose runtime helper because it is explicit and handles nullable numeric types too.

Why Nullable Support Matters

If you do reflection over models or DTOs, you will often encounter int?, decimal?, and similar nullable wrappers.

That is why this line matters:

csharp
type = Nullable.GetUnderlyingType(type) ?? type;

Without it, typeof(int?) would not match the numeric cases even though it clearly represents a nullable numeric value.

Explicit Type Whitelist

Another clear approach is to compare against exact known numeric types.

csharp
1using System;
2using System.Collections.Generic;
3
4public static class NumericTypes
5{
6    private static readonly HashSet<Type> Types = new()
7    {
8        typeof(byte), typeof(sbyte),
9        typeof(short), typeof(ushort),
10        typeof(int), typeof(uint),
11        typeof(long), typeof(ulong),
12        typeof(float), typeof(double),
13        typeof(decimal)
14    };
15
16    public static bool IsNumeric(Type type)
17    {
18        type = Nullable.GetUnderlyingType(type) ?? type;
19        return Types.Contains(type);
20    }
21}

This is slightly more verbose than TypeCode, but some teams prefer the directness because the supported set is visible immediately.

What About char, bool, and Enums

Even though some of these can participate in conversions or have underlying integer representations, they are usually not treated as numeric types for application logic.

Typical expectations:

  • 'char is not numeric'
  • 'bool is not numeric'
  • 'enum is not numeric for most validation purposes'

If your business rules differ, define that explicitly rather than assuming the runtime has the same definition you do.

Compile-Time Generic Constraints

If you are designing new generic numeric code in modern .NET, runtime reflection may not be the best tool. Newer generic math interfaces can express numeric requirements at compile time.

For example:

csharp
1using System.Numerics;
2
3public static T Add<T>(T left, T right) where T : INumber<T>
4{
5    return left + right;
6}
7
8Console.WriteLine(Add(2, 3));
9Console.WriteLine(Add(1.5m, 2.5m));

This does not answer “is this Type numeric?” at runtime, but it is often the better design if the real goal is to write generic numeric code safely.

Reflection Use Cases

Runtime numeric detection often shows up in:

  • object mappers
  • validation frameworks
  • serialization code
  • UI scaffolding or metadata inspection

In those scenarios, a TypeCode helper is usually enough and easier to maintain than complex dynamic logic.

Common Pitfalls

The biggest mistake is using IsPrimitive and assuming it means “numeric.” Another is forgetting nullable wrappers and therefore rejecting types like decimal?. Developers also sometimes include char or enums accidentally because they are backed by numeric representations, even though that is not the intended business meaning. Finally, if the actual problem is generic numeric computation, a reflection helper may be the wrong abstraction compared with modern generic math constraints.

Summary

  • There is no built-in Type.IsNumeric in C#.
  • For runtime checks, TypeCode or an explicit whitelist is the clearest solution.
  • Unwrap nullable types before testing.
  • Do not confuse numeric types with primitive types.
  • For new generic numeric algorithms, consider compile-time numeric interfaces instead of runtime reflection.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions