The .NET Framework is a set of libraries and a runtime, originally designed by Microsoft. All .NET programs compile to a bytecode called Microsoft Intermediate Language (MSIL). The MSIL is run by the Common Language Runtime (CLR).
Below you can find several examples of "Hello World" in various languages that support the .NET Framework. "Hello World" is a program that displays "Hello World" on the display device. It's used for illustrating the basic syntax for constructing a working program. It can also be used as a sanity test to make sure that a language's compiler, development environment, and runtime environment are all working correctly.
There are several kinds of collection:
Array
List
Queue
SortedList
Stack
Do not use the XmlSerializer
to parse HTML
. For this, special libraries are available like the HTML Agility Pack
The currently relevant HTTP/1.1 RFCs are:
There's also the following informational RFCs:
And the experimental RFC:
Related protocols:
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 IEnumerable
s 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
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:
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.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.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()
.See also: HTTP Clients
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.
The purpose of the Task Parallel Library is to simplify the process of writing and maintaining multithreaded and parallel code.
Some Use Cases*:
*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.
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 struct
s 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.
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.
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();
}
}
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.
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
).
System.Threading.Tasks.Dataflow
System.Threading.Tasks
System.Net.Http
System.Net
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).
Returns true if the file exists, false otherwise.
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.
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.
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:
"à".Length == 2
while you may expect 1
."\u00e0" == "\u0061\u0300"
(even if "\u00e0".Length != "\u0061\u0300".Length
). This is possible because of string normalization performed by String.Normalize()
method.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.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 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.
A note on parameterizing SQLs with Parameters.AddWithValue
: AddWithValue
is never a good starting point. That method relies on inferring the type of the data from what is passed in. With this, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char
/varchar
(without preceding "n") or date
do not have a corresponding .NET data type. In those cases, Add
with the correct data type should be used instead.
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.
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.
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.
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.
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.
A ReadOnlyCollection
provides a read-only view to an existing collection (the 'source collection').
Items are not directly added to or removed from a ReadOnlyCollection
. Instead, they are added and removed from the source collection and the ReadOnlyCollection
will reflect these changes to the source.
The number and order of elements inside a ReadOnlyCollection
cannot be modified, but the properties of the elements can be and the methods can be called, assuming they are in scope.
Use a ReadOnlyCollection
when you want to allow external code to view your collection without being able to modify it, but still be able to modify the collection yourself.
See Also
ObservableCollection<T>
ReadOnlyObservableCollection<T>
A ReadOnlyCollection
differs from an ImmutableCollection
in that you cannot edit an ImmutableCollection
once you created it - it will always contain n
elements, and they cannot be replaced or reordered. A ReadOnlyCollection
, on the other hand, cannot be edited directly, but elements can still be added/removed/reordered using the source collection.
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
.NET Framework provides implementation of many cryptographic algorithms. They include basically symmetric algorithms, asymmetric algorithms and hashes.
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:
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.
Why use JIT compilation?
Wikipedia Page for more information on JIT compilation in general: https://en.wikipedia.org/wiki/Just-in-time_compilation
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.
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:
You can also use a MemoryStream instead of a FileStream.
Exceptions
Exception | Condition |
---|---|
ArgumentException | The stream has already been closed, or the capabilities of the stream does not match the mode (eg: trying to write to a read only stream) |
ArgumentNullException | input stream is null |
ArgumentOutOfRangeException | mode has an invalid value |
InvalidDataException | See list below |
When a InvalidDataException is thrown, it can have 3 causes:
All information has been taken from this MSDN page