SoFunction
Updated on 2025-03-01

c#:CTS type system

1. Value type and reference type

C# is divided into two major categories: one is the reference type; the other is the value type.

Technically speaking, a reference type is a pointer pointing to specific data; while a value type actually stores data. Therefore, the reference type size is fixed (although it actually associates other parts, you don't need to pass these when passing the reference type, just pass pointers), and the value type has different sizes.

All types are derived from, including value type branches. All value types are subclasses, or subclasses of enumerations. And itself is a reference type. Therefore, the inheritance relationship has nothing to do with whether it is a value type. Users need to define different types through keywords such as class and struct.

User-defined classes, interfaces, arrays, and delegates are reference types; custom enums and structures are value types.

The difference between a structure and a class is that the base type of a structure cannot be customized, and the fixed is that in terms of structural design, a multi-layer inheritance model cannot be established. However, the structure can implement interfaces.

When a value type is converted to a reference type, if converted to a base type Object, it will produce a "boxing" operation. Technically, it is to copy the data to a new memory space and then point it with a pointer, so it is a resource-consuming operation. The corresponding "unboxing" is a reverse process.

2. Special types

A generic is not a type, but a shortcut to define a type. First use placeholders as part of the type definition, and give the corresponding part when actually defining the type to form the real type. For example, the C of class C<T>{} is not a type, but an unfinished template. You need to give the actual type of T to obtain the complete type. For example: C<int> Here is a C<int> type. Generics can be used to define reference types or value types.

Anonymous types are types defined in the new {member a;member b;} format, which are directly inherited from Object, and members are read-only. This type is mainly used to process temporary data objects.

nullable type, adding after the value type? indicates nullable type. The nullable type is an instance of the <T> generic structure. Mainly used in database programming.

3. Delegate type and interface type

The delegate type is derived from or, and belongs to the reference type. Delegate types are created through the keyword delegate. The speciality of delegate types is that they are mainly used to encapsulate functions, while structures and classes are used to encapsulate data and operations, where structures are biased towards data and classes are biased towards operations. It can be seen that these three custom types have their own focus.

Delegation is equivalent to a function pointer. It does not save the actual operation process, but maintains a pointer to the function. This is a bit similar to a reference type data relationship. You can initialize the delegate with the function name, or you can create an anonymous method or lambda equation to instantiate the delegate.

Anonymous methods are created by delegate{ statement} and are closures created within functions. A closure is a piece of code, but it can contain local variables of the host function.

lambda is an improvement in anonymous methods, such as (x,y)=>x+y, which can concisely describe simple algorithms.

The common point between delegate types and interface types is that they do not involve specific implementations, but focus on "forms", so they can achieve the purpose of separate specific implementations. The point where an interface is more powerful than a delegation is that an interface can define multiple function forms, while a delegation is only one, but this may be an advantage or a disadvantage. For example, you can define multiple delegations to link different instances; while multiple function forms of an interface can only be implemented in one instance.

Therefore, to connect the components, there are two options: 1. For different algorithm implementations or event notifications, it is best to use delegates; 2. For a set of associated operations, object interoperability, and interfaces are best.