Part of what makes C# programming (and .NET development in general) so easy is working with Types. C# and other .NET languages allow programmers to work directly with types, which represent the "type" of an object or structure, without working with instances.
.NET development with types is a powerful thing. So let's look at something simple, taking a type and creating a new object from it.
Normally you would create a new instance of an object with the C# new keyword. For example, say we want a new List<string> object:
List<string> myList = new List<string>();
The variable myList would then hold a single instance of the List<string> type. This is simple enough because we know the type of the object before hand. But C# variables can also be a type, for example:
Type myType = typeof(string);
So the variable myType does not hold an instance of an object, instead it holds a reference to the string type. Since the reference behaves like a variable, C# developers can type references in all sorts of ways, such as function parameters or in arrays.
A crucial part of working with variables is thus to be able to create a new object from a type-variable. Let's try an example with creating a List<string> object from a reference type.
Type listType = typeof(List<string>); List<string> instance = (List<string>)Activator.CreateInstance(listType);
Note that the CreateInstance function returns an object variable, so it needs to be cast into the proper type.
So what is the use of creating an object instance in such as complicated manner? Well like mentioned before, C# gives .NET developers the flexibility of working with type references as variables, which means programmers can pass them between functions and use them anywhere else that variables are used. This technique is especially powerful when combined with interfaces.