Introdution to Programming - C# Programming Fundamentals

Programming Fundamentals of C# shows the data types you can use within C#, how to declare variables and how to use functions and namespaces.

2,395 words, estimated reading time 9 minutes.
Introduction to Programming with C#

This article is part of a series of articles. Please use the links below to navigate between the articles.

  1. Learn to Program in C# - Full Introduction to Programming Course
  2. Introdution to Programming - C# Programming Fundamentals
  3. Guide to C# Data Types, Variables and Object Casting
  4. C# Operators: Arithmetic, Comparison, Logical and more
  5. Application Flow Control and Control Structures in C#
  6. Introduction to Object Oriented Programming for Beginners
  7. Introduction to C# Object-Oriented Programming Part 2
  8. C# Collection Types (Array,List,Dictionary,HashTable and More)
  9. Error and Exception Handling in C#
  10. Events, Delegates and Extension Methods
  11. Complete Guide to File Handling in C# - Reading and Writing Files
  12. Introduction to XML and XmlDocument with C#
  13. What is LINQ? The .NET Language Integrated Query
  14. Introduction to Asynchronous Programming in C#
  15. Working with Databases using Entity Framework
  16. All About Reflection in C# To Read Metadata and Find Assemblies
  17. Debugging and Testing in C#
  18. Introduction to ASP.Net MVC Web Applications and C#
  19. Windows Application Development Using .Net and Windows Forms
  20. Assemblies and the Global Assembly Cache in C#
  21. Working with Resources Files, Culture & Regions in .Net
  22. The Ultimate Guide to Regular Expressions: Everything You Need to Know
Introdution to Programming - C# Programming Fundamentals

C# is not just a programming language, it's a safety net for your code. It's a type-safe programming language, which means that each variable must be declared, and once declared, a variable of a given data type cannot be changed to another type.

What Are Variables in Programming?

In programming, variables are symbols used to represent data values that can change during the execution of a program. They provide a way to store and manipulate information temporarily within the program's memory.

Type safety allows the compiler to check your code to ensure that you don't try to divide a number by a string. This is done before the code is compiled, which would otherwise result in a program crash.

A practical programming approach is to use a variable for a specific task and create a new variable for a different task. This not only aligns with good programming practice but also enhances code maintainability by ensuring a variable's data type remains constant.

When declaring variables in C #, you start by specifying the type and then the name by which it will be accessed. You can also include an access modifier, such as public or private, which controls the variable's scope. Anyone can access public variables, while private variables can only be accessed within the current scope, such as the function or class it is declared.

C#
int myNumber;
string myString;
decimal accountBalance;

When declaring variables like this, they will be given the default value based on their type. Typically, this is 0 for numbers or empty strings. We'll look at the various basic types and their default values later. As shown in the example below, you can give a variable an initial value by adding an assignment to the declaration.

C#
int myNumber = 1;
string myString = "Some test string";
decimal accountBalance = 1.0M;

Because C# is a type-safe language, you cannot assign a string to a variable.

C#
int myNumber = "Hello World"; //This will not compile

You can also assign a variable the value of another variable of the same type.

C#
int x = 5;
int y;
y = x;

Variable assignment assigns the values of x to y. X will still retain its original value; Y is just given the value of X.

What are Data Types in C#?

In the .Net Framework, you can use many different types to hold data, from numbers, strings, dates and much more. We will cover the data types in more detail in a later tutorial; for now, we'll look at a few basic types. Remember, learning C # is a step-by-step process, and we're here to guide you through each step.

There are two broad data type categories: value and reference.

A value type directly contains its data. A variable of type int contains a value (e.g. 12345) and only a value. Each variable of a value type has its copy of the data. An operation on one variable does not affect another. Value types are stored in a memory location known as the stack.

Examples of Value types are int, float, struct, and enum.

Reference types contain a reference, or memory location, of their data. The data is stored as an object on the heap. Unlike value types, two or more reference types can point to the same memory location; thus, an operation on one variable can affect another. Reference types are instantiated with the new keyword.

Examples of Reference types are string, arrays, classes and delegates.

It is important to know the difference because it affects how you can manipulate the data each type holds.

If x is a variable and its type is a value type, then changing the value of x directly changes the data it contains.

If x is a variable and its type is a reference type, then changing the value of x is not the same as changing the data in the object to which the value of x refers.

I know that may be a bit heavy for some, but it's an important concept to understand.

What are Functions in Programming?

In the previous tutorial, we wrote a simple Hello World program in which we saw the Main method. We didn't explain what the Main method is or what it does.

The "Main" is a method that must exist in every program, as the compiler uses this to decide what to do when the program runs. This is called the entry point for the program.

Let's have a reminder and look at our Hello World again.

C#
using System;

class HelloWorld
{
  static void Main()
  {
    Console.WriteLine("Hello World!");
  }
}

The M is capital and is case-sensitive. The Main method must always be marked as static; otherwise, it cannot be run. Static means the method can be called without an instance of the class.

The next word, Void, is the data type that the method returns; in this case, void means nothing is returned). If the method were to return a number, then you would replace void with int.

All Methods are blocks of code, and a block of code is always encased within curly brackets (braces).

Methods are always executed sequentially from the top brace down to the bottom brace. The program exits when the compiler reaches the end of the Main method.

We can add another method to our project in much the same way as the Main method. After the closing brace of the Main method, we will add another method called "myMethod". We will write a line to the console stating that myMethod has been called within this method. We will then call myMethod from the Main method.

The code should look like this when you add our new method.

C#
using System;

class HelloWorld
{
  static void Main()
  {
    Console.WriteLine("Hello World!");
    myMethod();
  }

  static void myMethod()
  {
    Console.WriteLine("myMethod Called");
  }
}

When running the program, you should see something similar.

Hello World Output
Hello World Output

How to Pass Parameters to Methods

What do we do if you want to pass some data to your new method and have it return a value? How do you capture the result? And how do you pass a parameter? Let's have a look at using a simple program to add numbers.

Starting with a new console project, we will create a method called addNumbers, which will take two integers as parameters. This is done by defining a variable within the brackets of the method. A comma separates parameters.

C#
static void addNumbers(int x, int y)

This will tell the compiler that the addNumbers method will need to have two integers, x and y. This method can only be called with the correct number of parameters and must be of the right type.

C#
addNumbers(); // Will not work as there are no parameters
addNumbers(5); // Will not work as the method requires two parameters
addNumbers("1", "2"); // Will not work as these are strings
addNumbers(5, 5); // Will work 

You can copy this code over the top of the Hello World program if you like, or you can create a new project.

C#
using System;

class AddNumbersProgram
{
    static void Main()
    {
        addNumbers(5, 5);
    }

    static void addNumbers(int x, int y)
    {
        int z = x + y;
        Console.WriteLine($"Result of {x} + {y} = {z}");
        Console.ReadKey();
    }
}

When run, this program should show:

Result of 5 + 5 = 10

We have used $ to indicate a string interpolation here. This is a shorthand notation for treating a string literal as an interpolated string. An interpolated string is a string literal that might contain interpolated expressions or variables. When an interpolated string is resolved as a result string, items with interpolated expressions are replaced by the string representations of the expression results.

You can also use the string.Format function to achieve the same result.

C#
string.Format("Result of {0} + {1} = {2}", x, y, z);

You should avoid string concatenation, that is, appending one string to another, as it can be very costly to compute and will result in poor application performance. If you need to build strings, use string.Format or interpolated strings.

Returning a Value from a Function

Instead of outputting the calculation to the screen, you may return it to the calling method (the method where the addNumbers method was called from. In this case, Main).

We need to make a few changes to the method. We need to change the word void (which means the method does not return a value) into int (which means the method returns an integer number). The method declaration now becomes:

C#
static int addNumbers(int x, int y)

Now we need to remove the Console.WriteLine line and replace it with:

C#
return z;

Finally, we need to capture the return result within Main.

C#
int result = addNumbers(5, 5);

And that's all we need to do to make our method return a value. We need to change our calling function to pick up the result.

C#
using System;

class AddNumbersProgram
{
    static void Main()
    {
        int result = addNumbers(5, 5);
        Console.WriteLine("Result of addNumbers = {0}", result);
    }

    static int addNumbers(int x, int y)
    {
        int z = x + y;
        return z;
    } 
}

Suppose a method is to perform a calculation. In that case, it is far better to have it return the result independently rather than include formatting and other information, which can be used from other methods that may need the same calculation. By returning the formatted string, you are limiting that method to that particular task.

Variable and Object Naming Guidelines

Variable, method and class names have rules that govern how they should be named.

They must:

  • Be Unique
  • Start with a letter or underscore; they must not start with a number
  • Contain only letters, numbers and the underscore character
  • Not be reserved words or keywords

In addition to those rules, there are some recommendations for good practice and readability. Some of these are listed below:

  • Names should always be meaningful but not too lengthy.
  • You should not use single letter identifiers except for loop control (where you should use i,j and k) or for mathematical equations (e.g. x = x * y^2).
  • You should always use the data type most appropriate. For example, a variable to hold the day of the month would never rise above 31, so a byte would be a better data type over an int or decimal.

Using Namespaces in C#

The entire .Net framework is built using namespaces, the most important of which is System. A Namespace is a construct that can be used to organise code sections, be it classes, structs, other namespaces or even entire solutions. Namespaces are used to avoid code conflicts and group classes of similar functionality. Implementing namespaces in your projects is good practice, as it will aid code reuse in later projects.

Standard Namespaces

Let's play with our Hello World application in Visual Studio.

Remove the line using System; and hit Ctrl+Shift+B again to build the project. You'll notice that the compiler now flags up an error.

The name 'Console' does not exist in the current context

This is because the Console object exists within the System namespace. An error is raised since we have not told the compiler where to find the Console.

There are two methods to fix this problem. We can either add System before the Console object:

C#
System.Console.WriteLine("Hello World!");

A better method would be to use the "using" directive. This is because a namespace can contain another namespace, which can contain another namespace. This will lead to a large amount of unnecessary code typed in.

The first method of calling System.Console.WriteLine uses the fully qualified name, which is very similar to a telephone number consisting of country code plus area code. The compiler knows exactly where to find the Console. The second method, using System, tells the compiler to look in a namespace for the object.

You may have also noticed that Visual Studio Editor has put a wavy line under the word Console. This is its way of telling you where the problem lies. It is a very similar wavy line to the spell checker in Word. If you click on Console when underlined, you should see a yellow line under the last letter. If you now place your mouse over this yellow box, an icon will appear with a drop-down arrow next to it. Click on the arrow, and Visual Studio will prompt you for different ways to fix the problem.

IntelliSense
IntelliSense

This example asks us to select "using System" or "System.Console". If you select one of these actions, the editor will change the code accordingly. Hit Ctrl+Shift+B again and see how it successfully compiles.

In later tutorials, we will use other namespaces; a few are listed below.

  1. System.Data.SqlClient - Database Connection Objects
  2. System.IO - Input / Output Objects
  3. System.Xml.Schema - XML Reader and Writer Objects

Creating a Namespace

As I said previously, it is good practice to implement namespaces in your projects, so let's look at how to implement a namespace in our Hello World application.

C#
using System;

namespace MyHelloWorld
{
  class HelloWorld  
  {
    static void Main()
    {
      Console.WriteLine("Hello World!");
    }
  }
}

It's that easy! Just surround your classes with a namespace block, and you're done.

It can be even easier with a nice feature of the IDE. Select the classes you wish to include in the namespace to right-click the code with the mouse, select "Surround With..." and type namespace. The IDE will automatically add the namespace construct and braces and indent the code for you!

Avoid Conflicts by using Namespaces

Namespaces are primarily used to avoid code conflicts. You could have two developers working on different parts of the same project. They could inadvertently use the same class name for something, and namespaces could resolve the correct class.

Alternatively, you could be using third-party software from two companies, and they could use the same class names. Each different class with the same name would perform a slightly different function.

Examples of Namespaces to Avoid Conflicts

This simple example illustrates the use of two classes of the same name, each with a function of the same name. You can access the other class's methods directly and unambiguously by referencing the namespace.

C#
using System;

namespace myInhouseCode
{
    class myClass
    {
        static void Main()
        {
            Console.WriteLine("myInhouseCode Main");
            myMethod();
            myContractorsCode.myClass.myMethod();
            Console.ReadLine();
        }

        static void myMethod()
        {
            Console.WriteLine("myMethod Called From myInhouseCode");
        } 
    }
}

namespace myContractorsCode
{
    class myClass
    {
        public static void myMethod()
        {
            Console.WriteLine("myMethod Called from myContractors Code");
        }
    }
}

The output of this code is as follows:

Multiple Namespaces
Multiple Namespaces

In this example, we can see that although we have two classes of the same name and two methods of the same name, we can avoid conflicts by using namespaces, as namespaces allow us to find the function we require explicitly.

About the Author

Tim Trott is a senior software engineer with over 20 years of experience in designing, building, and maintaining software systems across a range of industries. Passionate about clean code, scalable architecture, and continuous learning, he specialises in creating robust solutions that solve real-world problems. He is currently based in Edinburgh, where he develops innovative software and collaborates with teams around the globe.

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

My website and its content are free to use without the clutter of adverts, popups, marketing messages or anything else like that. If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

There are no comments yet. Why not get the discussion started?

New comments for this post are currently closed.