Garbage Collector

  • 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> to IEnumerable<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 to IEqualityComparer<DerivedClass> because IEqualityComparer.Equals is 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.

object obj = str;

String can be represented as an object because it is reference type and inherits from System.Object.

Covariance is when object that is instantiated with a more derived type argument is assigned to an object instantiated with a less derived type argument.

IEnumerable<string> strings = new List<string>();

List<> inherits from IEnumerable<string> so can be represented as such.

Covariance in generic interface:

interface IEnumerable<out T>

Contravariance is when object that is instantiated with a less derived type argument is assigned to an object instantiated with a more derived type argument.

static void SetObject(object o) { }
Action<object> actObject = SetObject;  
Action<string> actString = actObject;

Contravariance in generic interface:

interface IEqualityComparer<in T>

.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 ArrayList i.e.)
  • information of exact type parameters used in a generic can be obtained at runtime by reflection

Further read:

https://learn.microsoft.com/en-us/dotnet/standard/generics/

Data structures in .NET

In table below official recommendations for choosing data structure for your needs:

GenericNon-GenericThread safePurpose
DictionaryHashtableConcurrentDictionarykey value pairs, lookup
ListArrayImmutableListaccess items by index
QueueConcurrentQueueFIFO queue
StackConcurrentStackLIFO queue
LinkedListaccess items sequentially
ObservableCollectionnotfications after modification
SortedListImmutableSortedSetauto sorted collection
HashSetImmutableHashSetdictionary of just keys (high performance set operations)

Further read:

https://learn.microsoft.com/en-us/dotnet/standard/collections/

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