Posts
automatic memory management allocates and releases memory prevents memory leaks and accessing dead objects provides memory safety virtual memory space defragments/compacts memory heap have 3 generations 0 - for new objects; 1 - for objects that lives through GC from 0 2 - for long living objects from 1 and 0 also Large Objects Heap (LOH) for big objects like arrays over 85,000 bytes Further read:
https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals?source=recommendations
Covariance and Contravariance
- enables implicit reference conversions for
- arrays
- delegates
- generic type arguments
- Covariance preserves assignment compatibility
- Contravariance reverses assignment compatibility
- allows for matching signatures of delegates and method groups
- to assign to delegates from method that returns more derived types - covariance
- to assign to delegates from method that returns less derived types - contravariance
- Covariance and Contravariance are supported in Generics for implicit conversions for type parameters
- allows method to have more derived return type than defined by generic type parameter of the interface
- this allows implicit conversions from one generic interface to another (from
IEnumerable<string>toIEnumerable<object>even if first does not inherits from second) - allows generic types to have less derived argument types than specified by the generic parameter of the interface (implementation of
IEqualityComparer<BaseClass>can be implicitly converted toIEqualityComparer<DerivedClass>becauseIEqualityComparer.Equalsis contravariant) - implicit conversions works for interfaces but not classes that implement from those interfaces (i.e. this won’t work
List<Object> list = new List<String>())
Assignment compatibility is when object of a more derived type is assigned to an object of a less derived type.
.NET Generics
Allow for:
- generalization of logic based on available types
- specify possible supported types
- re-usability of code
- type safety
- defers the exact specification of logic until the class or method is declared and instantiated by user code with all type parameters specified
- mostly used for collections (some non-generic versions of collection are not recommended like
ArrayListi.e.) - information of exact type parameters used in a generic can be obtained at runtime by reflection
Further read:
Data structures in .NET
In table below official recommendations for choosing data structure for your needs:
| Generic | Non-Generic | Thread safe | Purpose |
Dictionary | Hashtable | ConcurrentDictionary | key value pairs, lookup |
List | Array | ImmutableList | access items by index |
Queue | - | ConcurrentQueue | FIFO queue |
Stack | - | ConcurrentStack | LIFO queue |
LinkedList | - | - | access items sequentially |
ObservableCollection | - | - | notfications after modification |
SortedList | ImmutableSortedSet | auto sorted collection | |
HashSet | ImmutableHashSet | dictionary of just keys (high performance set operations) |
Further read:
Strings in .NET
sequential collection of chars immutable max 2GB or about 1 billion characters reference type are interned - CLR saves memory by maintaining a table, called the “intern pool”, that contains a single reference to each unique literal string declared or created programmatically in your program. Further read:
https://learn.microsoft.com/en-us/dotnet/api/system.string?view=net-7.0 https://learn.microsoft.com/en-us/dotnet/api/system.string.intern?view=net-6.0#remarks
What type can not be object field?
ref struct type can not be used as object field.
Further read:
`ref struct` types https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct
`ref struct` types
added as part of C# 7.2. defined with ref struct StructName always on the stack never part of heap cannot be element of an array cannot be field type of reference type can’t implement interfaces can’t be boxed can’t be type argument can’t be captured by closure of lambda or local function can’t be used in async methods can’t be used in iterators Further read:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct
Value types as fields in objects
Value types are stored in the heap when they are part of the reference type.
Reference types vs Value types
Reference types:
passed via reference reside on the heap subject to GC inherits from System.Object Value types:
passed via value reside on the stack, CPU registers or the heap no subject to GC inherits from System.ValueType Further read:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types https://www.infoworld.com/article/3043992/a-deep-dive-value-and-reference-types-in-net.html
.NET Type System
shared type system across all .net languages primitives data types library 5 kind of types: classes structures enumerations interfaces delegates Further read:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system
ThreadPool
provides a pool of threads can be used to execute tasks post work items process asynchronous I/O process timers Further read:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadpool?view=net-6.0
Task Parallel Library (TPL)
simplify process of adding parallelism and concurrency to application scales concurrency automatically data parallelism task based async programming data flow Further read:
https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl
Locking with integer
In short:
it will not work because it requires boxing and boxing will create new object for reference in lock every time code is executed so lock statement will not prevent anything.
Further read:
https://intellitect.com/blog/locking-a-block-of-code-with-an-integer/
Locking in .NET
lockstatement blocks execution of a code block for single thread that hold lock- the same thread can acquire and release lock again
- any other thread is blocked from the statement
- lock on dedicated instance only
- using the same instance on multiple
lockstatements may lead to deadlock - avoid using as lock
- Hold a lock for as short time as possible to reduce lock contention.
Below code block is translated by compiler
Thread vs task in . NET
task is asynchronous operation thread is abstraction on OS thread Further read:
https://www.c-sharpcorner.com/article/task-and-thread-in-c-sharp/