Pular para o conteúdo
ValidadorCNPJ Gerar CNPJ

C# · código pronto

Validar CNPJ alfanumérico em C#

Validador de CNPJ alfanumérico em C# / .NET 8, com atributo de validação para ASP.NET Core.

Testar um CNPJ agora Gerar massa de teste

Classe estática em C# 12 / .NET 8 sem pacotes externos, mais um ValidationAttribute para usar nos modelos do ASP.NET Core e do Entity Framework.

O algoritmo é sempre o mesmo: cada caractere vale o seu código ASCII menos 48 (0=0 … 9=9, A=17 … Z=42), os pesos vão de 2 a 9 da direita para a esquerda, soma-se tudo, divide-se por 11 e o dígito é 0 quando o resto é menor que 2, ou 11 menos o resto. Ver a conta detalhada.

Código completo

validação de CNPJ alfanumérico em C#
using System;
using System.Text.RegularExpressions;

namespace Exemplo.Documentos;

public static partial class Cnpj
{
    [GeneratedRegex("[^0-9A-Z]")]
    private static partial Regex NaoAlfanumerico();

    [GeneratedRegex(@"^[0-9A-Z]{12}\d{2}$")]
    private static partial Regex Formato();

    [GeneratedRegex(@"^(.)\1{13}$")]
    private static partial Regex Repetido();

    /// <summary>Remove máscara e normaliza para maiúsculas.</summary>
    public static string Limpar(string? valor) =>
        string.IsNullOrEmpty(valor)
            ? string.Empty
            : NaoAlfanumerico().Replace(valor.ToUpperInvariant(), string.Empty);

    /// <summary>Calcula um dígito do módulo 11 (valor do caractere = ASCII - 48).</summary>
    private static int Digito(ReadOnlySpan<char> sequencia)
    {
        var soma = 0;

        for (var i = 0; i < sequencia.Length; i++)
        {
            var valor = sequencia[i] - 48;
            var peso = ((sequencia.Length - 1 - i) % 8) + 2;
            soma += valor * peso;
        }

        var resto = soma % 11;

        return resto < 2 ? 0 : 11 - resto;
    }

    /// <summary>Devolve os dois dígitos verificadores da base de 12 caracteres.</summary>
    public static string CalcularDv(string baseCnpj)
    {
        var primeiro = Digito(baseCnpj);
        var segundo = Digito($"{baseCnpj}{primeiro}");
        return $"{primeiro}{segundo}";
    }

    /// <summary>Valida CNPJ numérico ou alfanumérico, com ou sem máscara.</summary>
    public static bool Valido(string? valor)
    {
        var cnpj = Limpar(valor);

        if (!Formato().IsMatch(cnpj) || Repetido().IsMatch(cnpj))
        {
            return false;
        }

        return CalcularDv(cnpj[..12]) == cnpj[12..];
    }

    /// <summary>Aplica a máscara 00.000.000/0000-00.</summary>
    public static string Formatar(string valor)
    {
        var cnpj = Limpar(valor);

        return cnpj.Length != 14
            ? cnpj
            : $"{cnpj[..2]}.{cnpj[2..5]}.{cnpj[5..8]}/{cnpj[8..12]}-{cnpj[12..]}";
    }
}

Testes e integração com o framework

ASP.NET Core + xUnit
// Atributo de validação
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public sealed class CnpjValidoAttribute : ValidationAttribute
{
    public override bool IsValid(object? valor) =>
        valor is null || (valor is string texto && Cnpj.Valido(texto));

    public override string FormatErrorMessage(string nome) => $"O campo {nome} não é um CNPJ válido.";
}

public class EmpresaDto
{
    [Required, StringLength(120)]
    public string RazaoSocial { get; set; } = string.Empty;

    [Required, CnpjValido]
    public string Documento { get; set; } = string.Empty;
}

// Teste
public class CnpjTests
{
    [Theory]
    [InlineData("12.ABC.345/01DE-35", true)]
    [InlineData("12abc34501de35", true)]
    [InlineData("11.222.333/0001-81", true)]
    [InlineData("11.222.333/0001-82", false)]
    [InlineData("12ABC34501DEAB", false)]
    public void ValidaCnpj(string entrada, bool esperado) =>
        Assert.Equal(esperado, Cnpj.Valido(entrada));

    [Fact]
    public void CalculaDvDoExemploOficial() =>
        Assert.Equal("35", Cnpj.CalcularDv("12ABC34501DE"));
}

Detalhes que costumam quebrar em C#

Casos de teste recomendados

Cubra pelo menos estes cenários — eles pegam praticamente todos os erros de implementação:

EntradaEsperadoO que testa
12.ABC.345/01DE-35válidoexemplo oficial, com máscara
12abc34501de35válidonormalização para maiúsculas
11.222.333/0001-81válidocompatibilidade com o formato numérico
11.222.333/0001-82inválidodígito verificador errado
12ABC34501DEABinválidoletra no dígito verificador
12ABC34501DE3inválidotamanho incorreto
00.000.000/0000-00inválidosequência repetida
"" / nullinválidoentrada vazia sem exceção

Precisa de mais massa de teste? O gerador produz até 500 CNPJs alfanuméricos válidos de uma vez, com opção de baixar em .txt.

O mesmo algoritmo em outras linguagens

Dúvidas sobre CNPJ alfanumérico em C#

Preciso de alguma biblioteca para validar CNPJ alfanumérico em C#?

Não. O código desta página usa apenas a biblioteca padrão de C# — são cerca de 30 linhas. Bibliotecas de terceiros só valem a pena se você também precisa de formatação, geração e validação de outros documentos; e, nesse caso, confira se a versão instalada já suporta o formato alfanumérico.

A mesma função valida CNPJ numérico e alfanumérico em C#?

Sim. Como o valor de cada dígito é o próprio dígito (código ASCII menos 48), o algoritmo alfanumérico produz o mesmo resultado do antigo para números. Você não precisa manter duas funções nem ramificar por formato.

Como testar se a implementação está certa?

Use o exemplo oficial da Receita Federal: a base 12ABC34501DE tem dígitos verificadores 35, formando 12.ABC.345/01DE-35. Confira também um CNPJ numérico conhecido, como 11.222.333/0001-81, e um inválido, como 11.222.333/0001-82.

O que mais precisa mudar além da função de validação?

O tipo da coluna no banco (de numérico para VARCHAR(14)), qualquer conversão para inteiro no caminho do dado, as máscaras de entrada e as regex espalhadas por validações e relatórios. A função de validação costuma ser a parte mais fácil da migração.