Sum and average calculator I've just written some code in an online compiler, and since I'm very new to C#, I wanted to ask what could be improved about the code.

The task of the program is simply to add up the numbers the user entered before and then calculate the average.

public static void Main()

{
    int input;
    int sum = 0;
    bool error = false;
    int[] numbers = new int[5];

    for(int i = 0; i &lt; numbers.Length; i++)
    {

        if (!error)
            Console.WriteLine("Please write a number:");

        if(Int32.TryParse(Console.ReadLine(), out input))
        {
            numbers[i] = input;
            sum += numbers[i];
            error = false;
        }
        else
        {
            Console.WriteLine("An error occured, please try again:");
            error = true;
            i--;
            continue;
        }
    }

    Console.WriteLine("");
    Console.WriteLine("Your typed in values:");
    for(int i = 0; i &lt; numbers.Length; i++)
    {
        Console.WriteLine(numbers[i]);
    }

    Console.WriteLine("");

    Console.WriteLine("The result of your numbers:");
    Console.WriteLine(sum);

    Console.WriteLine("The average of your numbers:");
    Console.WriteLine((double)sum / (double)numbers.Length);
}



The code works fine, but maybe I could do some things more effectively.
Would be glad to get some help :)  

Just to sum things up here is the console-output:  

Please write a number:
&gt; 4
Please write a number:
&gt; 2
Please write a number:
&gt; a
An error occured, please try again:
&gt; 6
Please write a number:
&gt; 4
Please write a number:
&gt; 8

Your typed in values:
4
2
6
4
8

The sum of your numbers:
24
The average of your numbers:
4.8


('>' = User input)
The code works, and it seems that you're take care of invalid input. But the logic of the workflow is not - well - that logic.


  int[] numbers = new int[5];


Here 5 is a magic number. Why five? Why not four or six or 20?

You should announce the number of input before asking for it (and maybe why).

Alternatively you could let the user enter a number of numbers to be calculated.




int sum = 0;



You probably have the sum variable for optimization reasons. Alternatively you could let the built in extension Sum() handle that:

numbers.Sum();





  if (!error)


You have this negation of a "negative" variable. Why not be positive and call it success:

if (success)
  Console.Write("Enter Number: ");




Instead of: 


    if (Int32.TryParse(Console.ReadLine(), out input))
    {
      numbers[i] = input;
      sum += numbers[i];



you could write:

    success = Int32.TryParse(Console.ReadLine(), out input);

    if (success)
    {
      ...
    }
    else
    {
      ...
    }





      continue;



I don't see any reason for calling continue in your loop? You use continue to step over the rest of the loop and reenter it - if the condition is still true, but here it is the last expression in the loop, so there is nothing to skip.



According to the overall design you should always split your code into meaningful methods in order to accommodate to principles like DRY and Single Responsibility:

For instance:

void Main()
{
  if (!GetCountOfNumbers(out int numCount))
    return;

  if (!GetUserInput(numCount, out int[] numbers, out int sum))
    return;

  PrintValues(numbers);
  Console.WriteLine("");
  PrintResult(sum, numbers.Length);
  Console.WriteLine("");
}


Where:

private bool GetCountOfNumbers(out int numCount)
{
  if (!GetIntInput("Enter count of Numbers", "Must be a positive number", x =&gt; x &gt; 0, out numCount))
  {
    Console.WriteLine("User aborted the calculation");
    return false;
  }

  return true;
}


and

private bool GetUserInput(int numCount, out int[] numbers, out int sum)
{
  numbers = new int[numCount];
  sum = 0;
  int input;

  for (int i = 0; i &lt; numCount; i++)
  {
    if (!GetIntInput($"Enter number {i + 1}", "Enter any valid integer (32 bit) value", x =&gt; true, out input))
    {
      Console.WriteLine("User aborted the calculation");
      return false;
    }

    numbers[i] = input;
    sum += input;
  }

  return true;
}


Both methods are calling GetIntInput() which could be defined as follows:

private bool GetIntInput(string message, string errorMessage, Predicate&lt;int&gt; predicate, out int result)
{
  result = default;

  while (true)
  {
    Console.Write($"{message} ['q' to Exit]: ");
    string input = Console.ReadLine();
    if (input == "q" || input == "Q")
      return false;

    if (int.TryParse(input, out int number) &amp;&amp; predicate(number))
    {
      result = number;
      return true;
    }
    Console.WriteLine($"Invalid input: {errorMessage}");
  }
}


It takes a message to the user, a predicate to validate the input against and an error message if the predicate returns false on the input, and it returns the result in an out variable (result). Further it allows the user to exit the input loop and then returns true or false accordingly.

In this design everything is counted for through descriptive method names and the logic in the workflow is easily understood and separately maintainable.

It could surely be done in more sophisticated ways, but as a simple user input driven console application like this, the above is a simple way to structure the code properly.