Skip to main content

Atributos em Parâmetros de Métodos no C# | CSharp

  • Classificação por impacto (contrato vs comportamento) | CSharp

Conceito fundamental

Atributos ([]) em parâmetros são metadados consumidos por diferentes camadas:

  • Compilador (Roslyn)
  • Runtime (.NET)
  • Frameworks (ASP.NET, serializers, etc.)
  • Interop (marshalling)

👉 Portanto, eles se dividem em dois grandes grupos:

  • Contrato (sem efeito direto em runtime)
  • Comportamento (afetam execução real)

Classificação geral

CategoriaTipoImpacto
Nullable AnalysisContratoCompilador
Binding (ASP.NET)ComportamentoRuntime
Caller InfoComportamentoCompilação
InteropComportamentoRuntime/Memory
DataAnnotationsComportamentoFramework
CustomDependeRuntime

1. Nullable Attributes (CONTRATO)

Namespace: System.Diagnostics.CodeAnalysis

✔ Afetam somente análise do compilador ✔ Não alteram execução ✔ Usados para eliminar warnings de nullability


[NotNull]

void Process([NotNull] string? value)
  • Garante que não será null após validação interna
  • Tipo: Contrato

[MaybeNull]

void Set([MaybeNull] string value)
  • Pode ser null mesmo sendo non-nullable
  • Tipo: Contrato

[AllowNull]

void Set([AllowNull] string value)
  • Permite passar null
  • Tipo: Contrato

[DisallowNull]

void Set([DisallowNull] string? value)
  • Proíbe null
  • Tipo: Contrato

[NotNullWhen(bool)]

bool IsValid([NotNullWhen(true)] string? value)
  • Garante não-null dependendo do retorno
  • Tipo: Contrato (flow analysis)

alt text


[MaybeNullWhen(bool)]

bool TryGet([MaybeNullWhen(false)] out string value)
  • Pode ser null dependendo do retorno
  • Tipo: Contrato

[NotNullIfNotNull]

string? Normalize([NotNullIfNotNull(nameof(input))] string? input)
  • Propagação de nullability
  • Tipo: Contrato

[MemberNotNull]

[MemberNotNull(nameof(_value))]
void Init(string? input)
  • Garante inicialização de membros
  • Tipo: Contrato

2. Binding Attributes (COMPORTAMENTO REAL)

Namespace: Microsoft.AspNetCore.Mvc

✔ Usados pelo ASP.NET via reflection ✔ Alteram como os parâmetros são preenchidos


[FromBody]

void Create([FromBody] UserDto dto)
  • Lê do corpo da requisição
  • Tipo: Comportamento (runtime)

[FromRoute]

void Get([FromRoute] int id)
  • Lê da URL
  • Tipo: Comportamento

[FromQuery]

void Search([FromQuery] string term)
  • Lê da query string
  • Tipo: Comportamento

[FromHeader]

void Auth([FromHeader] string token)
  • Lê do header HTTP
  • Tipo: Comportamento

3. DataAnnotations (COMPORTAMENTO – VALIDAÇÃO)

Namespace: System.ComponentModel.DataAnnotations

✔ Executados por frameworks (ex: ASP.NET) ✔ Não são apenas documentação


[Required]

void Create([Required] string name)
  • Validação automática
  • Tipo: Comportamento

[Range]

void SetAge([Range(0, 120)] int age)
  • Validação numérica
  • Tipo: Comportamento

[StringLength]

void SetName([StringLength(100)] string name)
  • Limite de tamanho
  • Tipo: Comportamento

4. Caller Info (COMPORTAMENTO EM COMPILE-TIME)

Namespace: System.Runtime.CompilerServices

✔ O compilador injeta valores automaticamente ✔ Alteram o código gerado (IL)


[CallerMemberName]

void Log(string msg, [CallerMemberName] string member = "")
  • Nome do método chamador
  • Tipo: Comportamento (compile-time)

[CallerArgumentExpression]

void Check(bool condition,
[CallerArgumentExpression("condition")] string expr = "")
  • Captura expressão original
  • Tipo: Comportamento (compile-time)

5. Interop Attributes (COMPORTAMENTO CRÍTICO)

Namespace: System.Runtime.InteropServices

✔ Influenciam memória e interoperabilidade ✔ Impacto direto no runtime


[MarshalAs]

void Send([MarshalAs(UnmanagedType.LPStr)] string value)
  • Define formato de marshalling
  • Tipo: Comportamento (baixo nível)

[In] / [Out]

void Process([In] byte[] input, [Out] byte[] output)
  • Direção dos dados
  • Tipo: Comportamento

6. Atributos opcionais e defaults


[Optional]

void Test([Optional] int value)
  • Parâmetro opcional
  • Tipo: Comportamento (interop/COM)

[DefaultParameterValue]

void Test([DefaultParameterValue(10)] int value)
  • Valor padrão
  • Tipo: Comportamento

7. Atributos customizados (DEPENDE DO USO)

public class MeuAtributoAttribute : Attribute
{
public string Nome { get; }
}

Uso:

void Metodo([MeuAtributo("x")] string param)

✔ Sozinho → apenas metadado ✔ Com reflection → comportamento

  • Tipo: Depende da implementação

Comparação direta

AtributoTipoImpacto
[NotNullWhen]ContratoCompilador
[MaybeNull]ContratoCompilador
[FromBody]ComportamentoRuntime
[Required]ComportamentoFramework
[CallerMemberName]ComportamentoCompile-time
[MarshalAs]ComportamentoRuntime/Memory
[MeuAtributo]DependeRuntime

Modelo mental final

  • Contrato puro → ajuda o compilador (não muda execução)
  • Comportamento indireto → frameworks usam (ASP.NET)
  • Comportamento direto → altera execução ou memória
  • Compile-time → altera código gerado

Insight importante

A maioria dos atributos modernos (principalmente nullable) existe para reduzir bugs sem custo de runtime, enquanto atributos de framework existem para orquestrar comportamento sem acoplamento direto — um padrão comum no ecossistema .NET