This is the 26th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

preface

C# describes a strongly typed language as statically typed.

Type systems are classified as strong/weak, secure/insecure, static/dynamic, and so on. C# 1’s type system is static, explicit, and secure. Until C# 4 introduced dynamic typing.

In some “strongly typed” definitions, it is clearly disqualifying C# to forbid any form of conversion (whether explicit or implicit). But in other definitions, it’s pretty close (or even equivalent) to static typing, which qualifies C#.

Static and dynamic types

C# is statically typed: each variable has a specific type, and that type is known at compile time.

object o = "hello";
Console.WriteLine(((string)o).Length);
Copy the code

Static type?

The term static is used to describe the compile-time types of expressions because they use unchanging data to analyze which operations are available. If a variable is declared as a Stream, its type does not change whether the value of the variable is MemoryStream, FileStream, or even a Stream type (including null references).

However, there can also be some dynamic behavior in a static type system, such as the actual implementation performed by a virtual method call depending on the object being invoked. Although this idea of “immutable information” is also the motivation behind static modifiers, it is easy to think of static members as belonging to the type itself, not to a specific instance of a type.

Dynamic type

The essence of dynamic typing is that variables contain values, but those values are not limited to a particular type, so the compiler cannot perform the same form of checking. Instead, the execution environment tries to interpret a given expression referring to a value in an appropriate way.

Explicit and implicit types

The distinction between explicit and implicit types only makes sense in statically typed languages.

  • For explicit types, the type of each variable must be explicitly specified in the declaration.

  • Implicit typing allows the compiler to infer the type of a variable based on its purpose.

Value type and reference type

Classes (declared using classes) are reference types, while structures (declared using structs) are value types. Special cases include the following:

  • An array type is a reference type, even if the element type is a value type (so int[] is a reference type even if int is a value type);
  • Enumerations (declared with enums) are value types;
  • Delegate types (declared using a delegate) are reference types;
  • Interface types (declared using interfaces) are reference types but can be implemented by value types.

What is the value of the expression?

  • An expression of a value type whose value is the value of the expression
  • An expression of a reference type whose value is a reference, not the object to which the reference refers. The value of the expression String.Empty is not an Empty String — it is a reference to the Empty String.

The value of a variable is stored at the location where it was declared.

  • Values of local variables are always stored in the stack, and values of instance variables are always stored where the instance itself is stored. This conclusion is only completely true in C# 1. As we’ll see later, in higher C# versions, local variables can end up stored in the heap under certain circumstances.

  • Reference type instances (objects) are always stored in the heap, as are static variables.