C# O Arquivo .csproj
Todo projeto C# tem um arquivo com o nome do projeto e a extensão .csproj (de C# project, "projeto C#"). Ele é pequeno, quase sempre umas dez linhas, mas manda em tudo: qual versão do .NET usar, se o programa é um executável ou uma biblioteca, se o compilador avisa sobre null, que nome o programa vai ter, que arquivos vão junto com ele, que pacotes ele usa. Nesta aula você vai ler o .csproj linha por linha e aprender a mudar as configurações mais comuns.
- As linhas do
.csprojque odotnet new consolecria:Project Sdk,PropertyGroup,OutputType,TargetFramework,ImplicitUsingseNullable. - O que são os usings implícitos e o arquivo
GlobalUsings.g.cs; como acrescentar um com<Using Include="…" />. - A mudar o nome e a versão do programa (
AssemblyName,Version) e a copiar um arquivo de dados junto com ele (ItemGroup). - A tratar avisos como erros (
TreatWarningsAsErrors) e a calar um aviso (NoWarn). LangVersion, as diretivas#:propertydos arquivos soltos .NET 10 e odotnet project convert.- Os erros
MSB4025,NETSDK1045eCS8805, e a propriedade escrita errado que ninguém avisa.
Todas as saídas desta aula são reais, feitas com o .NET 10 SDK (10.0.112) na máquina fictícia da Ana, no projeto ~/projetos/Lojinha, criado com dotnet new console -o Lojinha (veja Projetos e O Comando dotnet).
A ideia: a ficha técnica do projeto
Numa receita de bolo, antes do modo de fazer, vem a ficha: "rende 12 fatias, forno a 180 °C, tempo 40 minutos, contém glúten". A ficha não é o bolo, mas diz como ele deve ser feito. O .csproj é a ficha técnica do projeto. Os arquivos .cs são o "modo de fazer" (o código); o .csproj diz ao dotnet build como transformar esse código num programa.
Ele é escrito em XML, um formato de texto com etiquetas (em inglês, tags) entre < >, como o HTML das páginas da internet. Cada informação fica entre uma etiqueta de abertura e uma de fechamento, com o mesmo nome:
<Nome>valor</Nome> «abre com <Nome>, fecha com </Nome> (com a barra)»
1. O .csproj de um projeto novo
$ cat Lojinha.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
- <Project Sdk="Microsoft.NET.Sdk">
- "Projeto": a etiqueta que envolve o arquivo inteiro (ela fecha na última linha,
</Project>). OSdk="Microsoft.NET.Sdk"é um atributo: diz que este é um projeto .NET comum e traz centenas de regras prontas (onde ficam os.cs, como chamar o compilador, onde pôr o resultado). É por isso que o arquivo é tão curto: o resto vem do SDK. Sites usamMicrosoft.NET.Sdk.Web. - <PropertyGroup>
- "Grupo de propriedades": uma caixa com as configurações do projeto. Cada linha dentro dela é uma propriedade: um nome e um valor.
- <OutputType>Exe</OutputType>
- "Tipo de saída":
Exe(de executable) é um programa que dá para rodar. A outra opção comum éLibrary, uma biblioteca, que só serve para outros projetos usarem (veja Bibliotecas de Classes). - <TargetFramework>net10.0</TargetFramework>
- "Plataforma alvo": para qual versão do .NET o programa é feito.
net10.0é o .NET 10;net8.0, o .NET 8. Ela decide também a versão do C# (o .NET 10 usa o C# 14) e quais classes você pode usar. - <ImplicitUsings>enable</ImplicitUsings>
- "Usings implícitos: ligado". É por causa desta linha que você escreve
Console,List<T>eFilesem nenhumusingno começo do arquivo (seção 2). - <Nullable>enable</Nullable>
- "Anuláveis: ligado". Liga os avisos sobre
null: o compilador passa a separarstring(nunca nulo) destring?(pode ser nulo) (seção 3 e null e Tipos Anuláveis).
Repare no que não está ali: a lista dos arquivos .cs. O SDK compila automaticamente todos os .cs da pasta do projeto e das subpastas (menos bin e obj). Criou um Produto.cs? Ele já faz parte do projeto, sem mexer no .csproj.
<OutputType> e <outputtype> são etiquetas diferentes. Copie os nomes exatamente como aparecem nesta aula.
2. Os usings implícitos
Quando ImplicitUsings está ligado, o dotnet build escreve sozinho um arquivo de código na pasta obj e o compila junto com o seu:
$ cat obj/Debug/net10.0/Lojinha.GlobalUsings.g.cs // <auto-generated/> global using System; global using System.Collections.Generic; global using System.IO; global using System.Linq; global using System.Net.Http; global using System.Threading; global using System.Threading.Tasks;
- // <auto-generated/>
- "Gerado automaticamente": não edite; ele é reescrito a cada
build. O.g.no nome também quer dizer generated. - global using System;
- Um
usingcomglobalna frente vale para todos os arquivos do projeto, não só para este (veja Namespaces e using).SystemtrazConsole;System.Collections.Generic,ListeDictionary;System.IO,File;System.Linq, o LINQ;System.Threading.Tasks,Task.
Para ver a diferença, a Ana desligou (<ImplicitUsings>disable</ImplicitUsings>) e compilou um programa de duas linhas:
var itens = new List<string> { "caderno", "lápis" };
Console.WriteLine(itens.Count);
$ dotnet build 2>&1 | grep -E "warning|error|Aviso|Erro"
/home/ana/projetos/Lojinha/Program.cs(1,17): error CS0246: O nome do tipo ou do namespace "List<>" não pode ser encontrado (está faltando uma diretiva using ou uma referência de assembly?) [/home/ana/projetos/Lojinha/Lojinha.csproj]
/home/ana/projetos/Lojinha/Program.cs(2,1): error CS0103: O nome "Console" não existe no contexto atual [/home/ana/projetos/Lojinha/Lojinha.csproj]
«… as mesmas duas linhas, repetidas no resumo …»
0 Aviso(s)
2 Erro(s)
Sem os usings implícitos, nem o Console existe: seria preciso escrever using System; e using System.Collections.Generic; no começo. É assim que eram os programas até o .NET 5, e é por isso que código antigo começa com uma fileira de using. (No fim de cada mensagem, entre colchetes, vem o projeto em que o erro aconteceu. O dotnet build mostra cada erro duas vezes: quando acontece e no resumo do fim.)
Acrescentar um using para o projeto inteiro
A Ana usa StringBuilder (de System.Text, veja StringBuilder) em vários arquivos. Ela não está na lista acima:
var sb = new StringBuilder();
sb.Append("caderno, ");
sb.Append("lápis");
Console.WriteLine(sb.ToString());
$ dotnet build 2>&1 | grep -E " error " | head -1 /home/ana/projetos/Lojinha/Program.cs(1,14): error CS0246: O nome do tipo ou do namespace "StringBuilder" não pode ser encontrado (está faltando uma diretiva using ou uma referência de assembly?) [/home/ana/projetos/Lojinha/Lojinha.csproj]
Em vez de pôr using System.Text; em cada arquivo, ela acrescenta um item Using no .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Text" />
</ItemGroup>
</Project>
$ dotnet run caderno, lápis $ cat obj/Debug/net10.0/Lojinha.GlobalUsings.g.cs // <auto-generated/> global using System; global using System.Collections.Generic; global using System.IO; global using System.Linq; global using System.Net.Http; global using System.Text; global using System.Threading; global using System.Threading.Tasks;
- <ItemGroup>
- "Grupo de itens": a segunda caixa do
.csproj. OPropertyGroupguarda configurações (um valor cada); oItemGroupguarda listas de coisas: arquivos, pacotes, outros projetos, usings. - <Using Include="System.Text" />
- "Inclua o using
System.Text". A barra antes do>fecha a etiqueta ali mesmo: é uma etiqueta sem conteúdo, só com atributo. Oglobal using System.Text;apareceu no arquivo gerado.
Fazer isso num arquivo de código também vale: um arquivo Usings.cs com global using System.Text; tem o mesmo efeito. Experimente:
Missão: as duas abas são compiladas juntas, como num projeto. O Program.cs usa StringBuilder, que não está nos usings implícitos, e o build falha com CS0246. Sem mexer no Program.cs, escreva na aba Usings.cs a linha global using System.Text; e rode.
var sb = new StringBuilder();
sb.Append("caderno, ");
sb.Append("lápis");
Console.WriteLine(sb.ToString());
// os usings do projeto inteiro
// os usings do projeto inteiro global using System.Text;
3. Nullable: os avisos sobre null
Com <Nullable>enable</Nullable>, o compilador avisa quando você pode estar usando algo que vale null:
string? apelido = null;
Console.WriteLine($"Tamanho: {apelido.Length}");
$ dotnet build 2>&1 | grep -E "warning|error|Aviso|Erro"
/home/ana/projetos/Lojinha/Program.cs(2,31): warning CS8602: Desreferência de uma referência possivelmente nula. [/home/ana/projetos/Lojinha/Lojinha.csproj]
«… a mesma linha, repetida no resumo …»
1 Aviso(s)
0 Erro(s)
O aviso CS8602 ("uso de uma referência possivelmente nula") salvou a Ana: esse programa daria NullReferenceException. Com disable, o aviso some, e aparece outro, dizendo que o ? de string? não tem efeito:
$ dotnet build 2>&1 | grep -E "warning|error|Aviso|Erro"
/home/ana/projetos/Lojinha/Program.cs(1,7): warning CS8632: A anotação para tipos de referência anuláveis deve ser usada apenas em código em um contexto de anotações '#nullable'. [/home/ana/projetos/Lojinha/Lojinha.csproj]
«…»
1 Aviso(s)
0 Erro(s)
Deixe sempre enable, como o modelo cria. Projetos antigos (de antes do .NET 6) não têm essa linha, e por isso não mostram esses avisos.
4. Nome, versão e arquivos de dados
A Ana quer que o executável se chame loja (sem maiúscula, como os comandos do Linux), que o programa saiba a própria versão e que a tabela de preços precos.txt vá junto com ele. O .csproj ficou assim:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>loja</AssemblyName>
<Version>1.2.0</Version>
</PropertyGroup>
<ItemGroup>
<None Update="precos.txt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
caderno;12,50 lápis;1,99
using System.Reflection;
string versao = Assembly.GetExecutingAssembly().GetName().Version!.ToString();
Console.WriteLine($"Lojinha da Ana, versão {versao}");
foreach (string linha in File.ReadAllLines("precos.txt"))
{
string[] partes = linha.Split(';');
Console.WriteLine($"{partes[0],-10} R$ {partes[1]}");
}
$ dotnet build
Determinando os projetos a serem restaurados...
/home/ana/projetos/Lojinha/Lojinha.csproj restaurado (em 161 ms).
Lojinha -> /home/ana/projetos/Lojinha/bin/Debug/net10.0/loja.dll
Compilação com êxito.
0 Aviso(s)
0 Erro(s)
Tempo Decorrido 00:00:04.91
$ ls bin/Debug/net10.0/
loja
loja.deps.json
loja.dll
loja.pdb
loja.runtimeconfig.json
precos.txt
$ cd bin/Debug/net10.0 && ./loja && cd ../../..
Lojinha da Ana, versão 1.2.0.0
caderno R$ 12,50
lápis R$ 1,99
- <AssemblyName>loja</AssemblyName>
- "Nome do assembly": o nome dos arquivos gerados (
loja,loja.dll…). Sem ela, o nome é o do.csproj. Um assembly é o nome que o .NET dá a um.dllou executável compilado. Repare que a linhaLojinha -> …/loja.dllmostra os dois: o projeto continua se chamandoLojinha. - <Version>1.2.0</Version>
- A versão do programa, gravada dentro do
loja.dll. OAssembly.GetExecutingAssembly().GetName().Versiona lê de volta (veja Reflexão), com um quarto número,.0. O costume éMAIOR.MENOR.CORREÇÃO. - <None Update="precos.txt" … />
- Para o SDK, um
.txté um item do tipoNone("nenhum": não é para compilar).Update("atualize") muda as regras de um item que o SDK já conhece: aqui, a regra de cópia. - CopyToOutputDirectory="PreserveNewest"
- "Copie para a pasta de saída se for mais novo": o
precos.txtaparece embin/Debug/net10.0/, ao lado do executável. A outra opção éAlways("sempre").
File.ReadAllLines("precos.txt") procura na pasta atual do terminal. Por isso a Ana entrou em bin/Debug/net10.0 antes de rodar. Com dotnet run, a pasta atual é a do projeto, onde o precos.txt original está, e também funciona. Para não depender disso, use Path.Combine(AppContext.BaseDirectory, "precos.txt"), que é sempre a pasta do executável (veja Pastas e Caminhos).
5. Avisos: mais rígido ou mais calmo
TreatWarningsAsErrors: aviso vira erro
Num projeto sério, aviso ignorado vira defeito. Com <TreatWarningsAsErrors>true</TreatWarningsAsErrors> ("trate avisos como erros") no PropertyGroup, o build falha em qualquer aviso (veja Avisos do Compilador):
int naoUsada;
Console.WriteLine("oi");
$ dotnet build 2>&1 | grep -E "warning|error|Aviso|Erro" | head -3
/home/ana/projetos/Lojinha/Program.cs(1,5): error CS0168: A variável "naoUsada" está declarada, mas nunca é usada [/home/ana/projetos/Lojinha/Lojinha.csproj]
/home/ana/projetos/Lojinha/Program.cs(1,5): error CS0168: A variável "naoUsada" está declarada, mas nunca é usada [/home/ana/projetos/Lojinha/Lojinha.csproj]
0 Aviso(s)
O CS0168 é normalmente um warning; aqui saiu como error.
NoWarn: calar um aviso específico
Para desligar um aviso no projeto inteiro, use NoWarn com o código dele:
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);CS0168</NoWarn>
$ dotnet build 2>&1 | grep -E "warning|error|Aviso|Erro" | head -3
0 Aviso(s)
0 Erro(s)
- $(NoWarn)
- O
$( )lê o valor atual de uma propriedade. O SDK já põe alguns códigos noNoWarn; escrevendo$(NoWarn);CS0168, você acrescenta o seu à lista em vez de apagar os dele. - ;
- Separa os itens de uma lista:
$(NoWarn);CS0168;CS8602.
Use o NoWarn com moderação: calar um aviso não conserta o problema. Uma variável não usada se apaga.
6. Versão do C# e do .NET
LangVersion: travar a versão do C#
O TargetFramework já escolhe o C# certo (net10.0 → C# 14), e quase nunca você precisa mudar. Mas a propriedade LangVersion existe, e é útil para ver o que uma versão antiga não aceita. A Ana usou a palavra-chave field C# 14 numa propriedade (veja Propriedades):
var p = new Produto { Nome = " caderno " };
Console.WriteLine($"[{p.Nome}]");
class Produto
{
public string Nome
{
get;
set => field = value.Trim();
} = "";
}
$ dotnet run [caderno]
Com <LangVersion>13</LangVersion> no PropertyGroup:
$ dotnet build 2>&1 | grep -E "error" | head -2 /home/ana/projetos/Lojinha/Program.cs(6,19): error CS9260: O recurso "campo palavra-chave" não está disponível no C# 13.0. Use a versão da linguagem 14.0 ou superior. [/home/ana/projetos/Lojinha/Lojinha.csproj] «…»
A mensagem diz o recurso, a versão atual e a versão necessária (a tradução "campo palavra-chave" é do original field keyword, "a palavra-chave field"). Valores comuns: um número (12, 13, 14), latest (a mais nova que o compilador conhece) e preview (recursos ainda em teste).
TargetFramework: outra versão do .NET
Trocar para net8.0 faz o projeto ser compilado para o .NET 8 (o dotnet build baixa da internet as "referências" do .NET 8, e o C# vira o 12). Compila, mas, na máquina da Ana, que só tem o runtime do .NET 10, não roda:
$ dotnet run; echo "código de saída: $?" /home/ana/projetos/Lojinha/Program.cs(2,31): warning CS8602: Desreferência de uma referência possivelmente nula. [/home/ana/projetos/Lojinha/Lojinha.csproj] You must install or update .NET to run this application. App: /home/ana/projetos/Lojinha/bin/Debug/net8.0/loja Architecture: x64 Framework: 'Microsoft.NETCore.App', version '8.0.0' (x64) .NET location: /usr/lib/dotnet The following frameworks were found: 10.0.12 at [/usr/lib/dotnet/shared/Microsoft.NETCore.App] Learn more: https://aka.ms/dotnet/app-launch-failed To install missing framework, download: https://aka.ms/dotnet-core-applaunch?framework=Microsoft.NETCore.App&framework_version=8.0.0&arch=x64&rid=ubuntu.26.04-x64&os=ubuntu.26.04 código de saída: 150
"Você precisa instalar ou atualizar o .NET para rodar este aplicativo": o programa pede o runtime 8.0.0, e só o 10.0.12 foi encontrado. Um programa feito para o .NET 8 não roda sozinho num .NET 10 (veja Versões do C# e do .NET). Para um programa novo, deixe net10.0.
7. Arquivos soltos: #:property .NET 10
Um arquivo solto rodado com dotnet run arquivo.cs não tem .csproj... mas tem um escondido: o dotnet cria um projeto "virtual" para ele. Para mudar uma propriedade desse projeto, escreva uma diretiva #:property Nome=Valor no começo do arquivo:
#:property LangVersion=13
#:property Nullable=disable
var p = new Produto { Nome = " caderno " };
Console.WriteLine($"[{p.Nome}]");
class Produto
{
public string Nome
{
get;
set => field = value.Trim();
} = "";
}
$ dotnet run preco.cs /home/ana/cs/csproj/preco.cs(9,19): error CS9260: O recurso "campo palavra-chave" não está disponível no C# 13.0. Use a versão da linguagem 14.0 ou superior. Ocorreu uma falha no build. Corrija os erros de build e execute novamente. $ sed -i '1d' preco.cs $ dotnet run preco.cs [caderno]
O #:property LangVersion=13 fez o mesmo que o <LangVersion>13</LangVersion>. O sed -i '1d' apagou a primeira linha, e o programa voltou a compilar. (A outra diretiva, #:package, que traz pacotes, está em Pacotes NuGet.)
Do arquivo solto ao projeto: dotnet project convert
Quando o arquivo cresce e merece virar projeto, o dotnet faz a conversão e transforma as diretivas em propriedades:
$ dotnet project convert preco.cs
$ ls
preco
preco.cs
$ ls preco
preco.cs
preco.csproj
$ cat preco/preco.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<PublishAot>true</PublishAot>
<PackAsTool>true</PackAsTool>
<UserSecretsId>preco-7a1225a797ad0e935c00e2d01a8479b119ec6ea9614670c215fe58bd7891b396</UserSecretsId>
<Nullable>disable</Nullable>
</PropertyGroup>
</Project>
A pasta preco nova tem uma cópia do código e um .csproj com as configurações que um arquivo solto usa sem você ver. Além das quatro conhecidas, aparecem três que um dotnet new console não põe: PublishAot (publicar em código nativo, veja Publicar o Programa), PackAsTool (poder virar uma ferramenta do dotnet tool) e UserSecretsId (um nome único para guardar senhas de desenvolvimento fora do código). O Nullable é o disable que veio da diretiva. Pode apagar as três linhas se não for usá-las.
Referência: as propriedades mais usadas
No PropertyGroup | Valores | O que faz |
|---|---|---|
OutputType | Exe, Library | Programa ou biblioteca. |
TargetFramework | net10.0, net8.0… | A versão do .NET (e, com ela, a do C#). |
ImplicitUsings | enable, disable | Os global using automáticos. |
Nullable | enable, disable | Os avisos sobre null. |
AssemblyName | um nome | O nome do .dll e do executável. |
RootNamespace | um nome | O namespace que o editor usa nos arquivos novos. |
Version | 1.2.0 | A versão do programa. |
TreatWarningsAsErrors | true, false | Todo aviso vira erro. |
NoWarn | $(NoWarn);CS0168 | Desliga avisos pelo código. |
LangVersion | 13, 14, latest, preview | Trava a versão do C#. |
No ItemGroup | O que faz |
|---|---|
<Using Include="System.Text" /> | Um global using para o projeto todo. |
<None Update="dados.txt" CopyToOutputDirectory="PreserveNewest" /> | Copia o arquivo para a pasta do executável. |
<PackageReference Include="Nome" Version="1.0.0" /> | Usa um pacote do NuGet (veja Pacotes NuGet). |
<ProjectReference Include="../Outro/Outro.csproj" /> | Usa outro projeto (veja Bibliotecas de Classes). |
<Compile Remove="Rascunho.cs" /> | Tira um .cs da compilação. |
Quando dá errado
error MSB4025: Não foi possível carregar o arquivo de projeto.
$ dotnet build
/home/ana/projetos/Lojinha/Lojinha.csproj(4,22): error MSB4025: Não foi possível carregar o arquivo de projeto. The 'OutputType' start tag on line 4 position 6 does not match the end tag of 'OutputTipe'. Line 4, position 22.
FALHA da compilação.
«… a mesma linha, repetida …»
0 Aviso(s)
1 Erro(s)
O que aconteceu: o XML está quebrado. A linha 4 abre com <OutputType> e fecha com </OutputTipe>: "a etiqueta de abertura OutputType não combina com a de fechamento OutputTipe". O mesmo erro aparece se faltar um </…>, um > ou uma aspa.
Como resolver: vá à linha e à coluna indicadas ((4,22)) e deixe a abertura e o fechamento com o mesmo nome. Um editor com destaque de XML ajuda a achar a etiqueta errada.
error NETSDK1045: o SDK .NET atual não oferece suporte ao direcionamento .NET 11.0.
$ dotnet build Determinando os projetos a serem restaurados... /usr/lib/dotnet/sdk/10.0.112/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.TargetFrameworkInference.targets(184,5): error NETSDK1045: o SDK .NET atual não oferece suporte ao direcionamento .NET 11.0. Destina-se a .NET 10.0 ou inferior ou usa uma versão do .NET SDK compatível com .NET 11.0. Baixe o SDK .NET em https://aka.ms/dotnet/download [/home/ana/projetos/Lojinha/Lojinha.csproj] FALHA da compilação. «…»
O que aconteceu: o projeto pede net11.0, mas o SDK instalado é o do .NET 10, que não sabe compilar para uma versão mais nova que ele. Acontece ao baixar um projeto feito por alguém com um SDK mais novo. O começo da mensagem é o arquivo de regras do SDK onde o erro foi detectado: não é para você mexer nele.
Como resolver: troque para <TargetFramework>net10.0</TargetFramework> (se o código não usa nada do .NET 11) ou instale o SDK mais novo.
error CS8805: O programa que usa as instruções de nível superior precisa ser um executável.
$ dotnet run 2>&1 | tail -4 /home/ana/projetos/Lojinha/Program.cs(1,1): error CS8805: O programa que usa as instruções de nível superior precisa ser um executável. [/home/ana/projetos/Lojinha/Lojinha.csproj] Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O que aconteceu: o .csproj tem <OutputType>Library</OutputType>, mas o Program.cs tem código solto, fora de classes (as instruções de nível superior, veja Program.cs e o Main). Uma biblioteca não tem por onde começar a rodar.
Como resolver: para um programa, <OutputType>Exe</OutputType>. Para uma biblioteca, tire o código solto (só classes).
A Ana escreveu <Nulable>enable</Nulable> (com um l só) e compilou o programa do apelido.Length:
$ dotnet build 2>&1 | grep -E "warning|Aviso"
/home/ana/projetos/Lojinha/Program.cs(1,7): warning CS8632: A anotação para tipos de referência anuláveis deve ser usada apenas em código em um contexto de anotações '#nullable'. [/home/ana/projetos/Lojinha/Lojinha.csproj]
«…»
1 Aviso(s)
O que aconteceu: é o aviso de quando o Nullable está desligado. No PropertyGroup, qualquer nome é aceito: Nulable virou uma propriedade nova, que ninguém lê. O SDK não avisa nada, e o Nullable de verdade ficou com o valor padrão (desligado).
Como resolver: confira a grafia letra por letra, com as maiúsculas. Na dúvida, copie o nome da tabela de referência acima ou da documentação.
Exercícios
1. Programa ou biblioteca?
Complete para o projeto gerar um programa que dá para rodar:
2. Para o .NET 10
Complete o valor da plataforma alvo do .NET 10:
3. Aviso vira erro
Complete a propriedade que faz o build falhar em qualquer aviso:
4. Por que um projeto novo usa Console e List<T> sem nenhum using?
5. A Ana criou o arquivo Cliente.cs na pasta do projeto. O que precisa mudar no .csproj?
6. O dados.csv não aparece em bin/Debug/net10.0. Qual linha resolve?
Resumo
- O
.csprojé a ficha técnica do projeto, em XML:<Project Sdk="Microsoft.NET.Sdk">comPropertyGroup(configurações) eItemGroup(listas). - As quatro linhas do modelo:
OutputType(Exe),TargetFramework(net10.0),ImplicitUsingseNullable(enable). - Todos os
.csda pasta entram sozinhos. Os usings implícitos ficam emobj/…/NOME.GlobalUsings.g.cs; acrescente outros com<Using Include="…" />. AssemblyNamemuda o nome do executável;Version, a versão;<None Update="…" CopyToOutputDirectory="PreserveNewest" />copia arquivos de dados.TreatWarningsAsErrorsdeixa o projeto rígido;NoWarncala um aviso;LangVersiontrava o C#.- Arquivo solto:
#:property Nome=Valor; para virar projeto,dotnet project convert. - Propriedade com nome errado não dá erro nenhum: só não funciona.