Overview
.NET type classifications
Value types vs reference types
Primitive types vs composite types
Generic types
Types created from literal values
Algebraic types: sum vs product
Composite types
Created by combining other types
Can be generic (except
enum
)
Types
Version
Name
Ref. type
Value type
Types .NET
class
✅
❌
struct
, enum
❌
✅
Specific to C♯
C♯ 3.0
Anonymous type
✅
❌
C♯ 7.0
Value tuple
❌
✅
C♯ 9.0
record (class)
✅
❌
C♯ 10.0
record struct
❌
✅
Specific to F♯
Tuple, Record, Union
✅ (default)
✅ (opt-in)
F♯ 4.6
Anonymous Record
✅ (default)
✅ (opt-in)
👉 F♯ type features are stable and mature.
Type Location
Top-level :
namespace
, top-levelmodule
(F♯)Nested :
class
(C♯),module
(F♯)Not definable in
let
bindings,member
In F♯, all type definitions are made with the type
keyword
→ including classes, enums and interfaces!
→ but tuples don't need a type definition
Particularity of F♯ types / .NET types
Tuple, Record, Union are:
Immutable by default
Non-nullable by default
Equality and structural comparison (except with fields of
function
type)sealed
: cannot be inheritedSupport deconstruction, with the same syntax than for construction
Types with literal values
Literal values = instances whose type is inferred
Primitive types:
true
(bool
) -"abc"
(string
) -1.0m
(decimal
)Tuples C♯ / F♯ :
(1, true)
Anonymous types C♯ :
new { Name = "Joe", Age = 18 }
Records F♯ :
{ Name = "Joe"; Age = 18 }
☝ Note :
Types must be defined beforehand ❗
Exception: tuples and C♯ anonymous types: implicit definition
Algebraic data types (ADT)
Composite types, combining other types by product or sum.
Let's take the types A
and B
, then we can create:
The product type
A × B
:Contains 1 component of type
A
AND 1 of typeB
.Anonymous or named components
Sum type
A + B
:Contains 1 component of type
A
OR 1 of typeB
.
By extension, same for the product/sum types of N types.
Why Sum and Product terms?
It's related to the number of values:
bool
→ 2 values:true
andfalse
unit
→ 1 value()
int
→ infinite number of values
The number of values in the composed type will be:
The sum of numbers for a sum type:
N(A) + N(B)
The product of numbers for a product type:
N(A) * N(B)
Algebraic types vs Composite types
enum
✅
❌
F♯ Union
✅
❌
C♯ class
(1), interface
, struct
❌
✅
F♯ Record
❌
✅
F♯ Tuple
❌
✅
(1) C♯ classes in the broadest sense: → including modern variations like anonymous type, Value tuple and Record
👉 In C♯, only 1 sum type: enum
, very limited / union type 📍
Type abbreviation
Alias of another type: type [name] = [existingType]
Different use-cases:
// 1. Document code to avoid repetition
type ComplexNumber = float * float
type Addition<'num> = 'num -> 'num -> 'num // 👈 Also works with generics
// 2. Decouple (partially) usage / implementation
// → Easier to change the implementation (for a stronger type)
type ProductCode = string
type CustomerId = int
⚠️ Deleted at compile time → no type safety
→ Compiler allows int
to be passed instead of CustomerId
!
💡 It is also possible to create an alias for a module 📍
module [name] = [existingModule]
⚠️ It's NOT possible to create an alias for a namespace (≠ C♯)
Last updated
Was this helpful?