The single-responsibility principle - piece of software should have only one responsibility The open–closed principle - things should be open for extension but closed for modification The Liskov substitution principle - changing interface implementation should not brake software The interface segregation principle - it is better to have more specialized interfaces than single big one The dependency inversion principle - dependencies should be abstracted via interfaces Further read:
https://en.wikipedia.org/wiki/SOLID
Custom implementation is usually only necessary if default, reference equality is not enough. In example:
entities value based equality value equality of deserialized objects custom comparisons based on other criterias public class ImaginaryNumber : IEquatable<ImaginaryNumber> { public double RealNumber { get; set; } public double ImaginaryUnit { get; set; } public override bool Equals(object obj) { return Equals(obj as ImaginaryNumber); } public bool Equals(ImaginaryNumber other) { return other != null && RealNumber == other.RealNumber && ImaginaryUnit == other.ImaginaryUnit; } public override int GetHashCode() { return HashCode.Combine(RealNumber, ImaginaryUnit); } }
Controller type inherits from ControllerBase and have Views support ControllerBase type is better suited for APIs Further read:
https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-6.0
default application server for .net cross platform best performance and memory utilization may not have some advanced features of HTTP.sys on Windows may be used with proxy server or as internet facing server Further read:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-6.0
To handle exceptions on Controller/Action level Exception Filters are used.
[TypeFilter(typeof(SampleExceptionFilter))] public class ExceptionController : Controller Exception Filters are implemented using IExceptionFilter with OnExcetion method override to handle exceptions.
Exception Filters can be applied to Controller and Action level.
Further read:
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-7.0#exception-filters https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.filters.iexceptionfilter?view=aspnetcore-7.0
To add global exception handling in ASP.NET Core just use configuration method:
app.UseExceptionHandler
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-6.0#exception-handler-lambda
Pretty much everything. Default ASP.NET Core request handling pipeline is consisting of bunch of middlewares:
Authentication Authorization CORS HTTP Logging MVC Static Files other Whole list of built-in middlewares can be found here:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-7.0#built-in-middleware There is possibility to write custom middleware too.
app.Use(async(context,next)=>{// Do work that can write to the Response.awaitnext.Invoke();// Do logging or other work that doesn't write to the Response.});
Pure OWIN Middleware:
This rather would be used to integrate with OWIN middlewares written in different language, so that ASP.NET Core implementation directly is not possible.
defines standard way for middleware to be used in a pipeline to handle requests and provide responses
ASP.NET Core applications can interoperate with OWIN-based applications, servers and middleware
Microsoft.AspNetCore.Owin package provides two adapter implementations:
ASP.NET Core to OWIN
OWIN to ASP.NET Core
This allows ASP.NET Core to be hosted on top of an OWIN compatible server/host or for other OWIN compatible components to be run on top of ASP.NET Core.
each node is expression (method call, equality comparison, binary operation etc.) representing a piece of code
you can compile expression tree and run code it represent
enables dynamic code generation at runtime
LINQ queries on DBs are implemented with Expression Trees
used in the dynamic language runtime (DLR)
anonymous lambda expression can be converted to ExpressionTree via compiler (i.e. x => x*2 can be represented as tree instead of delegate or anonymous lambda function)
consistent model for working with data from various kinds of sources and formats (XML, SQL, ADO.NET, Datasets, .NET collections etc) 3 stages of working with LINQ: obtain data source create the query execute the query data sources implements IEnumerable<> and are called queryable types IQueryable<> interface inherits from IEnumerable<> generally it is better to use LINQ via IQueryable<> which produces deferred query instead of producing result immediately queries can be executed multiple times queries can be forced immediate execution via Count(), Max(), ToList() or ToArray() etc. LINQ to DB libraries (like EntityFramework) usually are implemented via Expression …
tracked entities are saved during SaveChanges() call entities being tracked when they are: returned from DB attached to context added as subentity tracking can be disabled (AsNoTracking() i.e.) Further read:
https://learn.microsoft.com/en-us/ef/core/change-tracking/
Pattern matching is used for:
testing expression to check if some value have certain characteristics safer compare because ‘==’ and ‘!=’ can be overloaded Examples:
a is int number sequence is IList<T> list switch statement:
command switch { Operation.SystemTest => RunDiagnostics(), Operation.Start => StartSystem(), Operation.Stop => StopSystem(), Operation.Reset => ResetToReady(), _ => throw new ArgumentException("Invalid enum value for command", nameof(command)), }; switch with ranges:
tempInFahrenheit switch { (> 32) and (< 212) => "liquid", < 32 => "solid", > 212 => "gas", 32 => …
obtain information about types and members at runtime create instances, invoke or access them dynamic code generation Further read:
https://learn.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection
· 35 words · ~1 min read
· updated
· in .NET, interview
Type Command framework-dependent executable for the current platform. dotnet publish framework-dependent executable for a specific platform. dotnet publish -r <RID> --self-contained false framework-dependent binary. dotnet publish self-contained executable. dotnet publish -r <RID> Further read:
https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent
Ahead of the time compilation to machine code
produces self-contained application which: starts quicker uses less memory does not require .NET runtime installed it is better for workloads with high deployment instances (clouds) makes runtime code generation impossible not all libraries are compatible Further read:
https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/
Just - in - time compiler.
part of CLR for all .net programs for all .net languages converts MSIL to native machine code compiles code when it is necessary at runtime also it is possible to pre-compile to native code at compile time instead Further read:
https://www.geeksforgeeks.org/what-is-just-in-time-jit-compiler-in-dot-net/
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
· 26 words · ~1 min read
· updated
· in .NET, interview
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
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
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.
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
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
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
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
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
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
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
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/
avoid doing AsyncOperation.Result parent method waits for Result while child method waits for parent thread to take control, after being done with async I/O both waits deadlock Further read:
https://medium.com/rubrikkgroup/understanding-async-avoiding-deadlocks-e41f8f2c6f5d https://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a-deadlock
Asynchronous programming patterns in .NET:
Asynchronous Programming Model (BeginOperation/EndOperation) Event-based Asynchronous Pattern (invoke event with result from async job) Task-based Asynchronous Pattern (Task<>) Ways of achieving asynchronous code in .NET
async, await Task class API (Run, WhenAll, WhenAny, etc.) ThreadPool.QueueUserWorkItem(ThreadProc); Further read:
async/await in .NET
https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/
There are two types of asynchronous operations in .NET.
I/O bound
CPU bound
For I/O bound async/await syntax should be used. TPL should not be used for this. async methods does not spawns new thread to hand le I/O work asynchronously.
For CPU bound operations TPL should be used (Task.Run). This spawns new thread. Performance testing should be done to check if overhead of new thread and context switching is not greater than actual work to be done.
· 143 words · ~1 min read
· updated
· in .NET, interview
informs GC that object does not need to be added to finalizer queue
finalizer execution is not deterministic and objects can live for long time in queue - this is optimization technique
to make sure that object disposes of any unamanaged resources even if Dispose will be not called we need to implement finalizer
Basically finalizer execution time is not deterministic. We cannot predict when this will be called and till that time - object is existing and still taking memory space. Since we are controlling creation and disposal of those resources we can say to GC: ‘Do not worry about that! It already had been taken care of!’. So this way object will be destroyed sooner, leaving this space to be used by something else possibly.
MyResource object have pointer which is unmanaged. This is why this class should implement IDisposable interface. Implementation should be correct according to recommended pattern (see below for documentation).
Closed What is asynchronous programming? What is TDD What is BDD What is DDD Open - to consider for yourself Interesting technical problem you solved lately Interesting technical problem you solved during your career What is the process of the MR/PR change review for you What is great success you accomplished lately? What skill did you improved lately? What is your greatest failure during your career? What was your biggest mistake?
software design approach software should be driven by business domain pieces of software should match the business domain goals: domain is primary focus complex design should base on model of the domain devs and business should continuously work on refining this model to address changes in business common language for defining a business model of the domain complex logic should be abstracted to domain Further read:
https://en.wikipedia.org/wiki/Domain-driven_design
based on TDD better collaboration between devs, QAs and business than TDD behavioral tests first, implementation second behavioral tests should be easy to understand, simple those tests should be written in specific language, possible to understood by business combines idea of unit tests naming, acceptance tests standard agile framework (As a XXX I want YY to achieve ZZ), and acceptance criteria with Gherkin Further read:
https://en.wikipedia.org/wiki/Behavior-driven_development
Test-driven development
software requirements are converted to tests cases *before* actual implementation implementation is done against all those test cases opposing to first writing an implementation then tests cases Further read:
https://en.wikipedia.org/wiki/Test-driven_development
software often waits for some I/O operation to complete (file operation, network call, database query etc.)
we can use this time for something productive instead to wait for data to be available or I/O operation to be completed
with asynchronous programming user can work in the meantime
not waiting for I/O operations synchronously enhances user experience
Of course this problem is much more complex. Modern software operates on much more different PC architecture than 20 years ago. Nowadays software must be asynchronous to appear more user friendly and to made better use of modern multi CPU architecture. Right now complex, professional software uses multiple processes, threads on multiple CPUs (CPU you buy is not really *single* CPU) or even utilize GPU for more complex computations (like i.e. video editing software). Before that we mostly had single threaded desktop applications that had ‘please wait’ or ’loading’ pop ups. Right now this is song of the past really and to achieve better User Interfaces that allow to edit tag of your post without changing whole post. With mobile devices on the rise and sometimes lousy cellular network those kind of designs would not be sensible or sometimes impossible to implement. Did you ever happened to reenter some chunk of data into some software because you lost it? Maybe network was down? Or you hit back button by mistake? Right now it belongs to past mostly. All of those would be hard to do with synchronous operations. Right now people are bit spoiled and they tend to leave the page/application if it appears to be slow and not every company can sell ‘one-in-the-market-necessary-for-your-work-software’ that you will be forced to use. And this is why we have asynchronous operations and this is why we have asynchronous programming model that allows us to program such operations.