Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Resolução] Faça como eu fiz: calculadora com sobrecarga de método

# Segindo o enunciado
Implementei 3 assinaturas diferêntes para o método Somar.
**Calculadora.cs**

internal class Calculadora
{
public static int Somar(int n1, int n2)
=> n1 + n2;

public static int Somar(int n1, int n2, int n3)
    => n1 + n2 + n3;

public static double Somar(double n1, double n2)
    => n1 + n2;

}

Percebi a importância das sobrecargas dos métodos, pois podem nos proporcionar mais flexibilidade em diversos cenários.


# Nova implementação 1
Aqui tenho apenas 2 métodos, um para calcular a soma de inteiros e um para calcular a soma de números do tipo double.
Isso já me dá uma grande vantagem, pois posso passar 2,3,8... números inteiros para serem somados com apenas um método(o mesmo vale para o uso com doubles).
O valores.Sum() irá retornar a soma de todos os números passados como parâmetro, sem a necessidade de iterar manualmente pela coleção.
**Calculadora.cs**

internal class Calculadora
{
public static int Somar(params int[] valores)
=> valores.Sum();

public static double Somar(params double[] valores)
    => valores.Sum();

}


# Nova implementação 2
Se a calculadora fosse trabalhar apenas com somas, seria possível ter uma classe genérica, que receberia o tipo durante a instanciação.
**Calculadora.cs**

internal class Calculadora2 where T : INumber
{
public static T Somar(params ReadOnlySpan numeros)
{
T total = T.Zero;
foreach (var numero in numeros)
total += numero;
return total;
}
}

O uso da interface **INumber** garante que só sejam instanciados objetos com tipos numéricos(int, double, decimal...)
**ReadOnlySpan<T>** isso garante que os dados sejam apenas lidos (read only) e também garante um ganho muito bom em termos de performance, pois os valores são lidos diretamente da Stack e eliminados quando a execução do método termina, sem precisar chamar o Garbage Collector, que também consome processamento.
**T.Zero é** um valor inicial neutro, meio que serve para ajudar o compilador a atribuir um formato correto, pois ele não sabe o que o T é incialmente.
Assim:
Se T for int, T.Zero é 0.
Se T for double, T.Zero é 0.0.
Se T for decimal, T.Zero é 0.0m.

**OBS:** Criei todos os métodos como estáticos, pois nenhum deles acessa membros de instância.
2 respostas
solução!

Oii, Gerson.

A sua evolução no exercício demonstra um excelente entendimento da linguagem C#. Você partiu da sobrecarga básica e explorou recursos avançados que tornam o código mais limpo e rápido.

1. Sobrecarga com params

O uso da palavra-chave params transforma o método em algo muito flexível. Em vez de criar uma sobrecarga para dois números, outra para três e outra para quatro, você permite que o usuário passe quantos argumentos desejar. O compilador trata isso como um array, mas a chamada do método fica limpa: Calculadora.Somar(1, 2, 3, 4, 5).

2. Generics e INumber<T>

Esta é a forma mais moderna de resolver o problema em C#. Introduzido no .NET 7 (Generic Math), o INumber<T> resolve a limitação histórica de não poder usar operadores aritméticos (+, -, *) em tipos genéricos.

3. Performance com ReadOnlySpan<T>

Sua escolha pelo ReadOnlySpan mostra preocupação com a alocação de memória. Diferente de um array comum ou de uma List, o Span aponta para um pedaço contínuo de memória sem criar cópias desnecessárias, o que é excelente para aplicações que processam grandes volumes de dados.

Na sua Nova implementação 2, você usou uma classe genérica Calculadora2<T>. Se quiser testar e tornar o uso ainda mais natural, você poderia manter a classe comum e tornar apenas o método genérico. Assim, não é necessário especificar o tipo na hora de instanciar a classe, pois o C# faz a inferência de tipo.

internal static class Calculadora3
{
    // O tipo T é inferido pelo que você passa no argumento
    public static T Somar<T>(params ReadOnlySpan<T> numeros) where T : INumber<T>
    {
        T total = T.Zero;
        foreach (var numero in numeros)
        {
            total += numero;
        }
        return total;
    }
}

// Uso:
var resultado = Calculadora3.Somar(10, 20, 30); // O C# entende que T é int

Continue firme nos estudos.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!

Muito obrigado Lorena, eu realmente não sabia que era possível utilizar o where direto no método, eu penssava que era somente na classe.
To gostando muito dos feedbacks aqui, pois a cada exercício eu aprendo muito com o próprio exercício, mas também com os feedbacks que recebo e também com os feedbacks dados a outros alunos.
Vlw mesmo.