Takeaways
- Scope is just stuff inside curly braces, and dictates access to variables
- If statements, loops, and functions all create new scope
- Namespaces are just scope that we use to organize programs
Up until now, the small programs we’ve written have consisted of only a single code file. But in the real world, code projects are made up of hundreds of code files!
How do we create a program with that much code, and that many files? There are a few concepts we need to discuss first before we get there.
Scope
Scope is basically just an area of code closed off by curly braces.
For example, conditionals and loops both use curly braces, to enclose the code they apply to. The code inside those curly braces is said to be in a separate scope:
//Outer scope
Console.WriteLine("It's Monday, nothing is awesome");
if(isAwesome)
{
//New level of inner scope!
int coolLevel = 5;
Console.WriteLine("My cool level is " + coolLevel);
}
for(int i = 0; i < 10; ++i)
{
//Another new scope, this time in a loop
Console.WriteLine("Yup, we're at {0} now", i);
}Where else have we seen this?… Oh yeah, functions!
int NumPokemonTypes(int gen)
{
if(gen <= 1)
{
return 15;
}
else if(gen <= 5)
{
return 17;
}
return 18;
}Scope is a way we control access to variables, and sequester code into different sections. Variables that are created within a scope can only be accessed in that scope, and any further INNER scope blocks. What does this mean? Let’s look at some examples:
public static void Main()
{
//outer scope
int x = 4;
if(x > 2)
{
//inner scope
Console.WriteLine("x value of {0} is too large! REDUCE BEAM!", x);
x = 2;
}
}The if statement above has curly braces which create a new scope. We can access the variable x in that scope, because it was created previously in an outer scope. You’ve already done this in your own code before.
However, you cannot use a variable created in an INNER scope in an OUTER scope. A variable is created within a particular scope, and once that scope ends, the variable ceases to exist:
public static void Main()
{
//outer scope
int x = 4;
if(x > 2)
{
//inner scope
Console.WriteLine("x value of {0} is too large! REDUCE BEAM!", x);
x = 2;
//Creating a variable in inner scope
int z = 15;
}
//outer scope again
//COMPILER ERROR! z is not a valid identifier anymore!
z = 18;
}This is also why, when we have separate functions, they don’t know anything about one another:
//This function has its own scope!
int AddTwoThings(int myNumber, int yourNumber)
{
//Variables here have no relation to
//any variables in SubtractTwoThings below
int result = myNumber + yourNumber;
return result;
}
//Another new scope, invisible to AddTwoThings
int SubtractTwoThings(int myNumber, int yourNumber)
{
//Variables here have no relation to
//any variables in AddTwoThings above
int result = myNumber - yourNumber;
return result;
}You don’t need if statements or loops or functions to make scope either… you can just make it! For the programs we’ll be writing in this class, you wont’ have compelling reasons to write anything similar to the code below, but it’s nice to know that it’s possible:
public static void Main()
{
//Scope, because I said so
//This serves no purpose, but whatever
{
int z = 5;
}
//Empty!
{
}
//Yup, more scope
{
Console.WriteLine("Whatever");
{
{
//Sure, why not?
string bob = "Bobert";
}
}
}
}
To organize code across many different files (within a single program), we can use something called a Namespace.
Namespaces
We’ve seen something like this before… right?
//This code is in Program.cs
namespace _3_Staircase
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("How many stairs in the staircase?");
int stairNum = int.Parse(Console.ReadLine());
StairFunc.PrintStairs(stairNum);
}
}
}Look at the very top of the code above… there’s a namespace thingy! What is that? What does it do?
A namespace is just a scope used across code files to organize all of the code in a particular project. By default, all the code that belongs to the same namespace can access most everything else within that namespace.
In some assignments, you will need to write functions in new files, separate from the Main function you’ve been using up until now:
//This code is in StairFunc.cs
namespace _3_Staircase
{
internal class StairFunc
{
//your code goes here!
}
}How does the Program.cs file know about this new function written in StairFunc.cs? Turns out it’s the namespace! Since they both share the “_3_Staircase” namespace, each file can access code from the other file. Namespaces can be most any name you want, so you don’t need to start them with an underscore or number… but you should definitely name them something appropriate for the code that namespace will contain!
About Classes
You’ll notice that we’re calling StairFunc.PrintStairs, instead of just calling PrintStairs by itself. This is similar to how we call Console.WriteLine instead of just WriteLine. Both Console and StairFunc are classes, but we’re not going to cover those for a hot minute… let’s stick to namespaces for now.