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
| Categoria | Tipo | Impacto |
|---|---|---|
| Nullable Analysis | Contrato | Compilador |
| Binding (ASP.NET) | Comportamento | Runtime |
| Caller Info | Comportamento | Compilação |
| Interop | Comportamento | Runtime/Memory |
| DataAnnotations | Comportamento | Framework |
| Custom | Depende | Runtime |
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)

[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
| Atributo | Tipo | Impacto |
|---|---|---|
[NotNullWhen] | Contrato | Compilador |
[MaybeNull] | Contrato | Compilador |
[FromBody] | Comportamento | Runtime |
[Required] | Comportamento | Framework |
[CallerMemberName] | Comportamento | Compile-time |
[MarshalAs] | Comportamento | Runtime/Memory |
[MeuAtributo] | Depende | Runtime |
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