Records

  • can be class or struct
  • creates methods overrides for enforcing value equality instead of reference equality:
    • Object.Equals
    • Object.GetHashCode
    • operators
      • ==
      • !=
  • implements IEquatable<> parameter
  • implements ToString
  • supports deconstruction
  • supports with expression
  • meant to be immutable

Positional records is a more concise syntax for record:

  • primary constructor parameters match the positional parameters of the record declaration
  • public init-only properties for each parameter

Further read:

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#characteristics-of-records

Is it possible to block GC?

We can.

  • for some critical part of application code using GC.TryStartNoGCRegion method.
  • using CER (Constrained Execution Regions) (obsolete)
  • with GC LatencyModes

Further read:

https://learn.microsoft.com/en-us/dotnet/api/system.gc.trystartnogcregion?redirectedfrom=MSDN&view=net-7.0#overloads

https://learn.microsoft.com/en-us/dotnet/framework/performance/constrained-execution-regions?redirectedfrom=MSDN

https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/latency

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/