-2

I am new to C#, my last programming language was C

I kept getting Use of unassigned local variable 'average' The average it is pertaining was the average /= 10;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int i, average;
            int[] scores = new int[10];

            Console.WriteLine("Enter 10 scores");
            for (i = 0; i < 10; i++)
            {
                scores[i] = Convert.ToInt32(Console.ReadLine());
            }

            for (i = 0; i < 10; i++)
            {
                average = scores[i] + scores[i + 1];
                i++;
            }

            average /= 10;

            Console.WriteLine("Average of All the Scores: {0}", average);
            Console.Read();
        }
    }
}
ktl159
  • 51
  • 1
  • 9
  • 1
    You can get rid of it by setting default value to the `average` variable `int average = 0;` – Fabio Aug 04 '19 at 04:51

2 Answers2

3

When you declare the variable 'average', set it to 0.

Matt
  • 25,943
  • 66
  • 198
  • 303
  • That gets rids of the error, but why does the compiler flag it up in this specific case? – Caius Jard Aug 04 '19 at 04:58
  • 3
    @Caius: the compiler error occurs because the compiler doesn't implement any static flow analysis that would confirm that the `average` variable is set. According to the "definite assignment" rules of C#, loops are ignored because it's possible for a loop to not iterate even once. Thus, `average` is _not_ definitely assigned, and thus the error. See marked duplicate, and of course the C# language specification, for more details. – Peter Duniho Aug 04 '19 at 05:01
  • 1
    Because it's only assigned a value inside an inner scope the compiler cannot for certain ensure it will reach. Even though in this case it's fairly obvious. So from its point of view, it might get to having to divide using average without it for sure having a value set. – Matt Aug 04 '19 at 05:03
  • @peterduniho thanks for the nugget of info! Very helpful to know about the loops bit- I guess I must never have come across that particular pattern of assignment in a loop – Caius Jard Aug 04 '19 at 05:10
  • @matt I think "inner scope" might be a bit broad because of you put `if(true) average =0;` before the error it goes away- this is the source of my confusion in this case, because I knew that inner scopes could assign a value the compiler would see - didn't know about the loops exclusion mentioned by Peter – Caius Jard Aug 04 '19 at 05:13
1

Here's a fixed version of your code, with comments as to why I made the change:

class Program
{
    static void Main(string[] args)
    {
        //fix the 'use of undefined' error
        int average = 0;
        int[] scores = new int[10];

        Console.WriteLine("Enter 10 scores");

        //it's better to scope loop iteration variables to the loop unless you specifically need them outside 
        for (int i = 0; i < 10; i++)
        {
            scores[i] = Convert.ToInt32(Console.ReadLine());
        }

        for (int i = 0; i < 10; i++)
        {
            //your old code would crash here, and had the wrong algorithm for calculating an average; it didn't sum all the entered values, just the last two 
            average += scores[i];
        }

        average /= 10;

        Console.WriteLine("Average of All the Scores: {0}", average);
        Console.Read();
    }
}

I was puzzled as to why the error occurred too because the second loop was clearly assigning a value and I knew that inner scopes could set values and the compiler would recognise them.. learning day for me too as I was formerly unaware that some loops are excluded even when they're set up so they look like they will definitely run. In simple terms it seems that when a loop is set up so that its running is conditional on a variable, the flow analysis considers that in some scenarios the loop might not run even though it's clear to the human reading the code that the loop will always run. Consider these:

//this is fine, flow analysis determines this loop will always run
int average;
while(true){
  average = 0;
  break;
}
average /= 10;

//this raises the same error even though we as a human can definitely see this loop will always run
int average;
int w = 0;
while(w<1){
  average = 0;
}
average /= 10;

Making the loop conditional on a variable meant the compiler wa and longer sure the variable was assigned

As another more involved example, you could also fix your error with this bizarre construct as your first loop:

        for (int i = 0; true; i++)
        {
    average = 0;
            scores[i] = Convert.ToInt32(Console.ReadLine());
    if(i >= 10)
        break;
        }

Again the compiler can be sure this loop will always run and your variable will be assigned

here's Peter's comment in case the other answer/the comment goes away:

the compiler doesn't implement any static flow analysis that would confirm that the average variable is set. According to the "definite assignment" rules of C#, loops are ignored because it's possible for a loop to not iterate even once. Thus, average is not definitely assigned, and thus the error. See marked duplicate, and of course the C# language specification, for more details.

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • I find it ironic that in your second loop, with `while(w<1)`, you have demonstrated another blind spot the compiler has with respect to code flow analysis. I.e. it hasn't noticed that the loop with never _exit_, and thus the fact that `average` is not definitely assigned (by C# rules) is irrelevant, because the statement where that error would occur is unreachable. – Peter Duniho Aug 04 '19 at 06:03