1
resposta

Faça como eu fiz: plataforma de cursos

Resolução:
ICurso.cs

namespace PraticandoC_05.PlataformaDeCursos10
{
    internal interface ICurso
    {
        void ValidarConteudo();
        void PublicarCurso();
    }
}

Instrutor.cs

namespace PraticandoC_05.PlataformaDeCursos10
{
    internal class Instrutor
    {
        public Instrutor(string? nome, string? especialidade)
        {
            Nome = nome;
            Especialidade = especialidade;
        }

        public string? Nome { get; }
        public string? Especialidade { get; }
    }
}

CursoProgramacao.cs

namespace PraticandoC_05.PlataformaDeCursos10
{
    internal class CursoProgramacao : ICurso
    {
        public CursoProgramacao(string? curso, Instrutor? instrutor)
        {
            Curso = curso;
            Instrutor = instrutor;
        }

        public string? Curso { get; }
        public Instrutor? Instrutor { get; }
        public void ValidarConteudo()
        {
            Console.WriteLine($"Validando conteúdo do curso de programação: {Curso}");
        }

        public void PublicarCurso()
        {
            Console.WriteLine($"Curso publicado com sucesso: {Curso} - Instrutora: {Instrutor!.Nome} ({Instrutor.Especialidade})\n");
        }
    }
}

CursoDesign.cs

namespace PraticandoC_05.PlataformaDeCursos10
{
    internal class CursoDesign : ICurso
    {
        public CursoDesign(string? curso, Instrutor? instrutor)
        {
            Curso = curso;
            Instrutor = instrutor;
        }

        public string? Curso { get; }
        public Instrutor? Instrutor { get; }
        public void ValidarConteudo()
        {
            Console.WriteLine($"Validando conteúdo do curso de design: {Curso}");
        }

        public void PublicarCurso()
        {
            Console.WriteLine($"Curso publicado com sucesso: {Curso} - Instrutora: {Instrutor.Nome} ({Instrutor.Especialidade})\n");
        }
    }
}

Program.cs

using PraticandoC_05.PlataformaDeCursos10;

Instrutor instrutor1 = new Instrutor("Carla", "Back-end");
ICurso curso1 = new CursoProgramacao("C# com POO", instrutor1);

Instrutor instrutor2 = new Instrutor("Felipe", "UI/UX");
ICurso curso2 = new CursoDesign("Design de Interfaces", instrutor2);

curso1.ValidarConteudo();
curso1.PublicarCurso();

curso2.ValidarConteudo();
curso2.PublicarCurso();
1 resposta

Olá, Christopher. Como vai?

Espetacular! Que fechamento de capítulo incrível. O seu código para a plataforma de cursos está absolutamente perfeito e consolida com maestria todos os pilares essenciais estudados até aqui.

Você aplicou a Composição com a classe Instrutor de forma impecável (um curso tem um instrutor) e usou os contratos da interface ICurso para guiar o comportamento polimórfico de CursoProgramacao e CursoDesign no seu Program.cs. Não há um único erro de sintaxe ou de modelagem conceitual no seu projeto.

Para fechar esse tópico com chave de ouro e preparar você para os próximos passos na sua jornada com o C#, vamos analisar o operador de negação de nulo (!) que você utilizou em uma das suas classes, que é um recurso moderno e muito importante da linguagem.


O Operador Null-Forgiving (!) em C#

Na classe CursoProgramacao.cs, dentro do método PublicarCurso(), você escreveu a seguinte linha:

Console.WriteLine($"Curso publicado com sucesso: {Curso} - Instrutora: {Instrutor!.Nome} ...")

Repare no uso do ponto de exclamação logo após a propriedade (Instrutor!.Nome). Na sintaxe moderna do C# (a partir do C# 8, com o recurso de Nullable Reference Types ativado), esse caractere é chamado de Null-Forgiving Operator (ou operador de indulgência nula).

Para que ele serve?

Quando você declara a sua propriedade como anulável (Instrutor?), o compilador do C# fica vigiando o seu código para te avisar se houver qualquer risco de acontecer o temido erro NullReferenceException (o famoso erro de objeto nulo).

Se você tentar acessar Instrutor.Nome sem antes colocar um if (Instrutor != null), o compilador pode gerar um alerta (warning) amarelo dizendo que o objeto pode estar nulo naquele momento.

Ao colocar o !, você está dizendo textualmente para o compilador:

"Fique tranquilo, C#! Eu sei que essa propriedade foi declarada como anulável, mas eu, como desenvolvedor, garanto que na hora em que este método rodar, o objeto Instrutor não estará nulo."

Isso silencia o aviso do compilador. É um recurso excelente para manter o painel de Warnings do seu Visual Studio limpo.


Um Detalhe Técnico: A Diferença para a classe CursoDesign

Um ponto curioso e super normal de acontecer ao digitar códigos extensos é que, na classe CursoDesign.cs, no mesmo método, você não precisou usar o operador:

Console.WriteLine($"Curso publicado com sucesso: {Curso} - Instrutora: {Instrutor.Nome} ...")

Se o seu compilador não reclamou de um aviso amarelo nessa linha, é bem provável que o C# tenha conseguido deduzir pelo fluxo do construtor que o objeto estaria seguro, ou as configurações de checagem estritas do seu arquivo de projeto (.csproj) estão tolerantes. De qualquer forma, entender o papel do ! vai te dar muita segurança quando você começar a construir APIs Web robustas com C# que conversam com bancos de dados.

Parabéns por toda a dedicação, pela organização cirúrgica dos namespaces e pela excelente evolução do seu design de software ao longo deste capítulo. Você dominou a diferença entre herança e composição!

Espero que possa ter lhe ajudado!