Author avatar

Christian Findlay

Declaring and Initializing Variables in C#

Christian Findlay

  • Dec 6, 2019
  • 7 Min read
  • 139 Views
  • Dec 6, 2019
  • 7 Min read
  • 139 Views
Languages Frameworks and Tools
C#

Introduction

The declaration and initialization of variables are fundamental to understanding any language. C# is a type-safe language, which means that all variables and constants in C# must have a type, and the declared type is immutable. In C#, types are either reference or value type. For further information on this, please see this article.

Variables can either be initialized in the same statement as the declaration or later in the code. This article discusses different ways of declaring and initializing variables, as well as when to use each way.

Local Variables

Local variables are variables declared inside a code block, which is usually part of a method, property, or delegate. Declarations specify the type followed by the name, and optionally the initialization. Initialization sets the variable to a new instance. It must be to a type that is compatible with the declaration type.

1
2
3
4
5
static void Main(string[] args)
{
    string a = "Hello World";
    Console.WriteLine(a);
}
cs

In the above code, the variable a is declared as a string and is initialized to "Hello World". The declaration below achieves precisely the same result.

1
var a = "Hello World";
cs

The var keyword specifies implicit typing. The code does not specify the type, and the compiler can infer the type from the initialization. The compiler recognizes that the literal inside the double quotes is a string and declares the variable as such. Implicitly typed variables should not be confused with variant types. var maintains C#'s type-safety mechanisms and does not allow a type change after declaration.

Explicitly typed variables can add readability to the code when it is not clear what type the compiler infers. Implicitly typed variables are less verbose and require fewer changes when refactoring. Teams should create guidelines around when to use explicit and implicit type declarations.

The code must initialize local variables before usage. This code causes a compilation error.

Use of unassigned local variable 'a'

1
2
3
4
5
static void Main(string[] args)
{
    string a;
    Console.WriteLine(a);
}
cs

Initialize the variable a to its default value of null or default to fix this issue.

1
2
3
4
5
static void Main(string[] args)
{
    string a = null;
    Console.WriteLine(a);
}
cs

Local variables have a maximum scope of the method that contains them. It means that code outside the method cannot use the declaration. For further information on the scope of variables, please see this article.

Fields

Fields are member variables that belong to a type. They can be specified with modifiers such as public or private to specify access. static fields only have one instance for the lifespan of the application. Types declare one variable instance for each non-static field on the type instantiated. Unlike local variables, fields require explicit type declaration, so the code cannot use var. Local variables should be converted to fields when more than one method or property needs to use the variable.

Fields are generally used to store data that is private to the type and not exposed via the public interface. It is possible to declare a field as public, but it is generally not considered best practice. Properties are generally used to expose variables publicly.

Unlike local variables, fields allow usage before initialization with code. This code does not cause a compilation or runtime error.

1
2
3
4
5
6
7
8
9
10
11
12
public class Messenger
{
    private DateTime _currentDate;

    public void SendMessage()
    {
        Console.WriteLine(_currentDate);

        _currentDate = DateTime.Now.Date;
        Console.WriteLine(_currentDate);
    }
}
cs

Output:

1/1/0001 12:00:00 AM

11/23/2019 12:00:00 AM

Notice that currentDate defaults to DateTime.MinValue . After the first WriteLine call, the code sets it to a new instance, which represents today's current date. Code can initialize fields before construction next to the declaration, like so.

1
2
3
4
public class Messenger
{
    private DateTime _currentDate = DateTime.Now.Date;
}
cs

Object Initializers and Collection Initializers

Object initializers offer a shorthand way of initializing a type's member variables. Consider this class.

1
2
3
4
5
public class Values
{
    public string A { get; set; }
    public string B { get; set; }
}
cs

This code creates an instance of Values and initializes the two properties.

1
2
3
4
5
6
7
8
9
class Program
{
    static void Main(string[] args)
    {
        var values = new Values();
        values.A = "A";
        values.B = "B";
    }
}
cs

This can be shortened like so:

1
2
3
4
5
6
7
class Program
{
    static void Main(string[] args)
    {
        var values = new Values { A = "A", B = "B" };
    }
}
cs

This reduces the verbosity of the code and often makes it more readable.

Use caution when initializing values from methods or properties that may throw an exception. The values property in this code never changes to a reference other than null.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Program
{
    static void Main(string[] args)
    {
        Values values = null;

        try
        {
            values = new Values
            {
                A = ThrowException(),
                B = "B"
            };
        }
        catch
        {
        }

        Console.WriteLine($"values is null {values == null}");
        Console.ReadLine();
    }


    public static string ThrowException()
    {
        throw new Exception();
    }
}
cs

Output:

values is null True

Initialize collections and arrays with collection initializers. This code creates a list of integers with three elements.

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    var numbers = new List<int> { 1, 2, 3 };

    foreach (var number in numbers)
    {
        Console.WriteLine(number);
    }

    Console.ReadLine();
}
cs

Output:

1

2

3

Declaring and Initializing Anonymous Types

Anonymous types are types without a name. Declare them in the scope of a code block. They can be useful for specific tasks like dynamically building an object to serialize to JSON and sending it to a RESTful service.

1
2
3
4
5
6
7
8
9
10
class Program
{
    static void Main(string[] args)
    {
        var values = new { A = "A", B = "B" };
        Console.WriteLine(values.A);
        Console.WriteLine(values.B);
        Console.ReadLine();
    }
}
cs

Output:

A

B

Anonymous types are type-safe. The code cannot modify declared members after declaration. Use anonymous types sparingly. C# works best with explicit type naming, and anonymous types often become confusing for the reader.

Conclusion

Variables always have a type in C#. Type-safety is fundamental to the language and separates it from languages like JavaScript. Developers should pay attention to the differences between value and reference types. They should make decisions about when to use explicit vs. implicit types, and use object and collection initializers where appropriate.

0