.NET Framework

Topics related to .NET Framework:

Getting started with .NET Framework

Collections

XmlSerializer

HTTP clients

Exceptions

LINQ

The LINQ built-in methods are extension methods for the IEnumerable<T> interface that live in the System.Linq.Enumerable class in the System.Core assembly. They are available in .NET Framework 3.5 and later.

LINQ allows for simple modification, transformation, and combination of various IEnumerables using a query-like or functional syntax.

While the standard LINQ methods can work on any IEnumerable<T>, including the simple arrays and List<T>s, they can also be used on database objects, where the set of LINQ expressions can be transformed in many cases to SQL if the data object supports it. See LINQ to SQL.

For the methods that compare objects (such as Contains and Except), IEquatable<T>.Equals is used if the type T of the collection implements that interface. Otherwise, the standard Equals and GetHashCode of the type (possibly overriden from the default Object implementations) are used. There are also overloads for these methods that allow to specify a custom IEqualityComparer<T>.

For the ...OrDefault methods, default(T) is used to generate default values.

Official reference: Enumerable class

Lazy Evaluation

Virtually every query that returns an IEnumerable<T> is not evaluated immediately; instead, the logic is delayed until the query is iterated over. One implication is that each time someone iterates over an IEnumerable<T> created from one of these queries, e.g., .Where(), the full query logic is repeated. If the predicate is long-running, this can be a cause for performance issues.

One simple solution (when you know or can control the approximate size of the resulting sequence) is to fully buffer the results using .ToArray() or .ToList(). .ToDictionary() or .ToLookup() can fulfill the same role. One can also, of course, iterate over the entire sequence and buffer the elements according to other custom logic.

ToArray() or ToList()?

Both .ToArray() and .ToList() loop through all elements of an IEnumerable<T> sequence and save the results in a collection stored in-memory. Use the following guidelines to determine which to choose:

  • Some APIs may require a T[] or a List<T>.
  • .ToList() typically runs faster and generates less garbage than .ToArray(), because the latter must copy all the elements into a new fixed-size collection one more time than the former, in almost every case.
  • Elements can be added to or removed from the List<T> returned by .ToList(), whereas the T[] returned from .ToArray() remains a fixed size throughout its lifetime. In other words, List<T> is mutable, and T[] is immutable.
  • The T[] returned from.ToArray() uses less memory than the List<T> returned from .ToList(), so if the result is going to be stored for a long time, prefer .ToArray(). Calling List<T>.TrimExcess() would make the memory difference strictly academic, at the cost of eliminating the relative speed advantage of .ToList().

Networking

NuGet packaging system

NuGet.org:

NuGet is the package manager for the Microsoft development platform including .NET. The NuGet client tools provide the ability to produce and consume packages. The NuGet Gallery is the central package repository used by all package authors and consumers.

Images in examples courtesy of NuGet.org.

Reflection

Dictionaries

HTTP servers

Settings

Task Parallel Library (TPL)

Purpose And Use Cases

The purpose of the Task Parallel Library is to simplify the process of writing and maintaining multithreaded and parallel code.

Some Use Cases*:

  • Keeping a UI responsive by running background work on separate task
  • Distributing workload
  • Allowing a client application to send and receive requests at the same time (rest, TCP/UDP, ect)
  • Reading and/or writing multiple files at once

*Code should be considered on a case by case basis for multithreading. For example, if a loop only has a few iterations or only does a small amount of the work, the overhead for parallelism may outweigh the benefits.

TPL with .Net 3.5

The TPL is also available for .Net 3.5 included in a NuGet package, it is called Task Parallel Library.

Custom Types

Typically a struct is used only when performance is very important. Since value types live on the stack, they can be accessed much quicker than classes. However, the stack has much less room than the heap, so structs should be kept small (Microsoft recommends structs take up no more than 16 bytes).

A class is the most-used type (of these three) in C#, and is generally what you should go with first.

An enum is used whenever you can have a clearly defined, distinct list of items that only need to be defined once (at compile time). Enums are helpful to programmers as a lightweight reference to some value: instead of defining a list of constant variables to compare to, you can use an enum, and get Intellisense support to make sure you don't accidentally use a wrong value.

DateTime parsing

Memory management

Performance-critical applications in managed .NET applications can be severely impacted by the GC. When the GC runs, all other threads are suspended until it completes. For this reason, it is recommended to carefully evaluate the GC processes and determine how to minimize when it runs.

Managed Extensibility Framework

One of MEF's big advantages over other technologies that support the inversion-of-control pattern is that it supports resolving dependencies that are not known at design-time, without needing much (if any) configuration.

All examples require a reference to the System.ComponentModel.Composition assembly.

Also, all the (Basic) examples use these as their sample business objects:

using System.Collections.ObjectModel;

namespace Demo
{
    public sealed class User
    {
        public User(int id, string name)
        {
            this.Id = id;
            this.Name = name;
        }

        public int Id { get; }
        public string Name { get; }
        public override string ToString() => $"User[Id: {this.Id}, Name={this.Name}]";
    }

    public interface IUserProvider
    {
        ReadOnlyCollection<User> GetAllUsers();
    }
}

SpeechRecognitionEngine class to recognize speech

To use SpeechRecognitionEngine, your Windows version needs to have speech recognition enabled.

You have to add a reference to System.Speech.dll before you can use the speech classes.

System.Reflection.Emit namespace

System.Runtime.Caching.MemoryCache (ObjectCache)

JSON Serialization

JavaScriptSerializer vs Json.NET

The JavaScriptSerializer class was introducted in .NET 3.5 and is used internally by .NET's asynchronous communication layer for AJAX-enabled applications. It can be used to work with JSON in managed code.

Despite the existence of the JavaScriptSerializer class, Microsoft recommends using the open source Json.NET library for serialization and deserialization. Json.NET offers better performance and a friendlier interface for mapping JSON to custom classes (a custom JavaScriptConverter object would be needed to accomplish the same with JavaScriptSerializer).

TPL Dataflow

Libraries Used in Examples

System.Threading.Tasks.Dataflow

System.Threading.Tasks

System.Net.Http

System.Net

Difference between Post and SendAsync

To add items to a block you can either use Post or SendAsync.

Post will try to add the item synchronously and return a bool saying whether it succeeded or not. It may not succeed when, for example, a block has reached its BoundedCapcity and has no more room for new items yet. SendAsync on the other hand will return an uncompleted Task<bool> that you can await. That task will complete in the future with a true result when the block cleared its internal queue and can accept more items or with a false result if it's declining permanently (e.g. as a result of cancellation).

File Input/Output

Returns true if the file exists, false otherwise.

Platform Invoke

Code Contracts

Code contracts allow for compile or runtime analysis of pre/post conditions of methods and invariant conditions for objects. These conditions may be used to ensure callers and return value match valid states for application processing. Other uses for Code Contracts include documentation generation.

VB Forms

ForEach

Use it at all?

You might argue that the intention of the .NET framework is that queries do not have any side effects and the ForEach method is by definition causing a side effect. You might find your code more maintainable and easier to test if you use a plain foreach instead.

Strings

In .NET strings System.String are sequence of characters System.Char, each character is an UTF-16 encoded code-unit. This distinction is important because spoken language definition of character and .NET (and many other languages) definition of character are different.

One character, which should be correctly called grapheme, it's displayed as a glyph and it is defined by one or more Unicode code-points. Each code-point is then encoded in a sequence of code-units. Now it should be clear why a single System.Char does not always represent a grapheme, let's see in real world how they're different:

  • One grapheme, because of combining characters, may result in two or more code-points: is composed by two code-points: U+0061 LATIN SMALL LETTER A and U+0300 COMBINING GRAVE ACCENT. This is the most common mistake because "à".Length == 2 while you may expect 1.
  • There are duplicated characters, for example à may be a single code-point U+00E0 LATIN SMALL LETTER A WITH GRAVE or two code-points as explained above. Obviously they must compare the same: "\u00e0" == "\u0061\u0300" (even if "\u00e0".Length != "\u0061\u0300".Length). This is possible because of string normalization performed by String.Normalize() method.
  • An Unicode sequence may contain a composed or decomposed sequence, for example character U+D55C HAN CHARACTER may be a single code-point (encoded as a single code-unit in UTF-16) or a decomposed sequence of its syllables , and . They must be compared equal.
  • One code-point may be encoded to more than one code-units: character 𠂊 U+2008A HAN CHARACTER is encoded as two System.Char ("\ud840\udc8a") even if it is just one code-point: UTF-16 encoding is not fixed size! This is a source of countless bugs (also serious security bugs), if for example your application applies a maximum length and blindly truncates string at that then you may create an invalid string.
  • Some languages have digraph and trigraphs, for example in Czech ch is a standalone letter (after h and before i then when ordering a list of strings you will have fyzika before chemie.

There are much more issues about text handling, see for example How can I perform a Unicode aware character by character comparison? for a broader introduction and more links to related arguments.

In general when dealing with international text you may use this simple function to enumerate text elements in a string (avoiding to break Unicode surrogates and encoding):

public static class StringExtensions
{
    public static IEnumerable<string> EnumerateCharacters(this string s)
    {
        if (s == null)
            return Enumerable.Empty<string>();

        var enumerator = StringInfo.GetTextElementEnumerator(s.Normalize());
        while (enumerator.MoveNext())
            yield return (string)enumerator.Value;
    }
}

Expression Trees

Expression trees are data structures used to represent code expressions in the .NET Framework. They can be generated by code and traversed programmatically to translate the code to another language or execute it. The most popular generator of Expression Trees is the C# compiler itself. The C# compiler can generate expression trees if a lambda expression is assigned to a variable of type Expression<Func<...>>. Usually this happens in the context of LINQ. The most popular consumer is Entity Framework's LINQ provider. It consumes the expression trees given to Entity Framework and generates equivalent SQL code which is then executed against the database.

Threading

System.Diagnostics

ADO.NET

CLR

Process and Thread affinity setting

The processor affinity of a thread is the set of processors it has a relationship to. In other words, those it can be scheduled to run on.

Processor affinity represents each processor as a bit. Bit 0 represents processor one, bit 1 represents processor two, and so on.

Dependency Injection

Problems Solved By Dependency Injection

If we didn't use dependency injection, the Greeter class might look more like this:

public class ControlFreakGreeter
{
    public void Greet()
    {
        var greetingProvider = new SqlGreetingProvider(
            ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
        var greeting = greetingProvider.GetGreeting();
        Console.WriteLine(greeting);
    }
}

It's a "control freak" because it controls creating the class that provides the greeting, it controls where the SQL connection string comes from, and it controls the output.

Using dependency injection, the Greeter class relinquishes those responsibilities in favor of a single responsibility, writing a greeting provided to it.

The Dependency Inversion Principle suggests that classes should depend on abstractions (like interfaces) rather than on other concrete classes. Direct dependencies (coupling) between classes can make maintenance progressively difficult. Depending on abstractions can reduce that coupling.

Dependency injection helps us to achieve that dependency inversion because it leads to writing classes that depend on abstractions. The Greeter class "knows" nothing at all of the implementation details of IGreetingProvider and IGreetingWriter. It only knows that the injected dependencies implement those interfaces. That means that changes to the concrete classes that implement IGreetingProvider and IGreetingWriter will not affect Greeter. Neither will replacing them with entirely different implementations. Only changes to the interfaces will. Greeter is decoupled.

ControlFreakGreeter is impossible to properly unit test. We want to test one small unit of code, but instead our test would include connecting to SQL and executing a stored procedure. It would also include testing the console output. Because ControlFreakGreeter does so much it's impossible to test in isolation from other classes.

Greeter is easy to unit test because we can inject mocked implementations of its dependencies that are easier to execute and verify than calling a stored procedure or reading the output of the console. It doesn't require a connection string in app.config.

The concrete implementations of IGreetingProvider and IGreetingWriter might become more complex. They, in turn might have their own dependencies which are injected into them. (For example, we'd inject the SQL connection string into SqlGreetingProvider.) But that complexity is "hidden" from other classes which only depend on the interfaces. That makes it easier to modify one class without a "ripple effect" that requires us to make corresponding changes to other classes.

Globalization in ASP.NET MVC using Smart internationalization for ASP.NET

Smart internationalization for ASP.NET page

The benefit of this approach is that you don't have to clutter controllers and other classes with code to look up values from .resx files. You simply surround text in [[[triple brackets.]]] (The delimiter is configurable.) An HttpModule looks for a translation in your .po file to replace the delimited text. If a translation is found, the HttpModule substitutes the translation. If no translation is found, it removes the triple brackets and renders the page with the original untranslated text.

.po files are a standard format for supplying translations for applications, so there are a number of applications available for editing them. It's easy to send a .po file to a non-technical user so that they can add translations.

Task Parallel Library (TPL) API Overviews

The Task Parallel Library is set of public types and APIs that dramatically simplify the process of adding parallelism and concurrency to an application. .Net. TPL was introduced in .Net 4 and is the recommended way to write multi threaded and parallel code.

TPL takes care of work scheduling, thread affinity, cancellation support, state management, and load balancing so that the programmer can focus on solving problems rather than spending time on common low level details.

System.IO

Unit testing

Serial Ports

System.IO.File class

Synchronization Contexts

A Synchronization Context is an abstraction that allows consuming to code to pass units of work to a scheduler, without requiring awareness of how the work will be scheduled.

Synchronization contexts are traditionally used to ensure that code is run on a specific thread. In WPF and Winforms applications, a SynchronizationContext representing the UI thread is provided by the presentation framework. In this way SynchronizationContext can be thought of as a producer-consumer pattern for delegates. A worker thread will produce executable code (the delegate) and queue it or consumption by the UI message loop.

The Task Parallel Library provides features for automatically capturing and using synchronization contexts.

Using Progress<T> and IProgress<T>

ReadOnlyCollections

Regular Expressions (System.Text.RegularExpressions)

System.Net.Mail

It is important to Dispose a System.Net.MailMessage because every single attachment contains a Stream and these Streams need to be freed as soon as possible. The using statement ensures that the Disposable object is Disposed also in case of Exceptions

Encryption / Cryptography

.NET Framework provides implementation of many cryptographic algorithms. They include basically symmetric algorithms, asymmetric algorithms and hashes.

Parallel processing using .Net framework

JSON in .NET with Newtonsoft.Json

.NET Core

By itself, .NET Core includes a single application model -- console apps -- which is useful for tools, local services and text-based games. Additional application models have been built on top of .NET Core to extend its functionality, such as:

  • ASP.NET Core
  • Windows 10 Universal Windows Platform (UWP)
  • Xamarin.Forms

Also, .NET Core implements the .NET Standard Library, and therefore supports .NET Standard Libraries.

The .NET Standard Library is an API spec that describes the consistent set of .NET APIs that developers can expect in each .NET implementation. .NET implementations need to implement this spec in order to be considered .NET Standard Library compliant and to support libraries that target the .NET Standard Library.

JIT compiler

Stack and Heap

It's worth noting that on declaring a reference type, its initial value will be null. This is because it does not yet point to a location in memory, and is a perfectly valid state.
However, with the exception of nullable types, value types must typically always have a value.

Work with SHA1 in C#

Work with SHA1 in C#

Garbage Collection

The Garbage Collector is aimed to lower the program cost in terms of allocated memory, but doing so has a cost in terms of processing time. In order to achieve a good overall compromise, there are a number of optimizations that should be taken into consideration while programming with the Garbage Collector in mind:

  • If the Collect() method is to be explicitly invoked (which should not often be the case anyway), consider using the "optimized" mode which finalizes dead object only when memory is actually needed
  • Instead of invoking the Collect() method, consider using the AddMemoryPressure() and RemoveMemoryPressure() methods, which trigger a memory collection only if actually needed
  • A memory collection is not guaranteed to finalize all dead objects; instead, the Garbage Collector manages 3 "generations", an object sometimes "surviving" from a generation into the next one
  • Several threading models may apply, depending on various factors including setup fine tuning, resulting in different degrees of interference between the Garbage Collector thread and the other application thread(s)

Reading and writing Zip files

Write to and read from StdErr stream

Upload file and POST data to webserver

Acronym Glossary