Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Respond to @akoeplinger feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
richlander committed Apr 20, 2015
1 parent 7684ead commit 60ab41f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 37 deletions.
5 changes: 5 additions & 0 deletions Documentation/README.md
Expand Up @@ -13,6 +13,11 @@ Product Instructions
- [Testing CoreCLR Changes](test-instructions.md)
- [Creating a Custom DNX](dnx-instructions.md)

.NET Primer
===========

- [.NET Primer](dotnet-primer.md)

Book of the Runtime
===================

Expand Down
25 changes: 23 additions & 2 deletions Documentation/assembly-format.md
@@ -1,5 +1,26 @@
.NET Assembly File Format
=========================

The .NET binary format is based on the Windows [PE file](http://en.wikipedia.org/wiki/Portable_Executable) format. In fact, .NET class libraries are conformant Windows PEs, and appear on first glance to be Windows dynamic link libraries (DLLs). This is a very useful characteristic on Windows, where they can masquerade as native DLLs and get some of the same treatment (e.g. OS load, PE tools).
CPU-agnostic and OS-agnostic. It is also fully specified and standardized. As a result, you can use class libraries within any application using any .NET implementation.
The .NET platform defines a binary file format - "assembly" - that is used to fully-describe and contain .NET programs. Assemblies are used for the programs themselves as well as any dependent libraries. A .NET program can be executed as one of more assemblies, with no other required artifacts, beyond the appropriate .NET runtime. Native dependencies, including operating system APIs, are a separate concern and are not contained within the .NET assembly format, although are sometimes described with this format (e.g. WinRT).

> Each CLI component carries the metadata for declarations, implementations, and references specific to that component. Therefore, the component-specific metadata is referred to as component metadata, and the resulting component is said to be self-describing -- from ECMA 335 I.9.1, Components and assemblies.
The format is fully specified and standardized as [ECMA 335](dotnet-standards.md). All .NET compilers and runtimes use this format. The presense of a documented and infrequently updated binary format has been a major benefit (arguably a requirement) for interoperatibility. The format was last updated in a substantive way in 2005 (.NET 2.0) to accomodate generics and processor architecture.

The format is CPU- and OS-agnostic. It has been used as part of .NET runtimes that target many chips and CPUs. While the format itself has Windows heritage, it is implementable on any operating system. It's arguably most significant choice for OS interopertability is that most values are stored in little-endian format. It doesn't have a specific affinity to machine pointer size (e.g. 32-bit, 64-bit).

The .NET assembly format is also very descriptive about the structure of a given program or library. It describes the internal components of an assembly, specifically: assembly references and types defined and their internal structure. Tools or APIs can read and process this information for display or to make programmatic decisions.

Format
======

The .NET binary format is based on the Windows [PE file](http://en.wikipedia.org/wiki/Portable_Executable) format. In fact, .NET class libraries are conformant Windows PEs, and appear on first glance to be Windows dynamic link libraries (DLLs) or application executables (EXEs). This is a very useful characteristic on Windows, where they can masquerade as native executable binaries and get some of the same treatment (e.g. OS load, PE tools).

![Assembly Headers](images/assembly-headers.png)

Assemblies headers from ECMA 335 II.25.1, Structure of the runtime file format.

Processing the Assemblies
=========================

It is possible to write tools or APIs to process assemblies. Assembly information enables making programmatic decisions at runtime, re-writing assemblies, providing API intellisense in an editor and generating documentation. [System.Reflection](https://msdn.microsoft.com/library/system.reflection.aspx) and [Mono.Cecil](http://www.mono-project.com/docs/tools+libraries/libraries/Mono.Cecil/) are good examples of tools that are frequently used for this purpose.
14 changes: 9 additions & 5 deletions Documentation/class-libraries.md
@@ -1,18 +1,18 @@
.NET Class Libraries
====================

Class libraries are the [shared library](http://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries) concept for .NET. They enable you to componentize useful functionality into modules that can be used by multiple applications. They can also be used as a means of loading functionality that is not needed or not known at application startup.
Class libraries are the [shared library](http://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries) concept for .NET. They enable you to componentize useful functionality into modules that can be used by multiple applications. They can also be used as a means of loading functionality that is not needed or not known at application startup. Class libraries are described using the [.NET Assembly file format](assembly-format.md).

There are three types of class libraries that you can use:

- **Platform-specific** class libraries have access to all the APIs in a given platform (e.g. .NET Framework 4.6, Xamarin iOS), but can only be used by apps and libraries that target that platform.
- **Platform-specific** class libraries have access to all the APIs in a given platform (e.g. .NET Framework, Xamarin iOS), but can only be used by apps and libraries that target that platform.
- **Portable** class libraries have access to a subset of APIs, and can be used by apps and libraries that target multiple platforms.
- **.NET Core** class libraries are a merger of the platform-specific and portable library concept into a single model that provides the best of both.

Platform-specific Class Libraries
=================================

Platform-specific libraries are bound to a single .NET platform (e.g. .NET Framework 4.6 on Windows) and can therefore take significant dependencies on a known execution environment. Such an environment will expose a known set of APIs (.NET and OS APIs) and will maintain and expose expected state (e.g. Windows registry).
Platform-specific libraries are bound to a single .NET platform (e.g. .NET Framework on Windows) and can therefore take significant dependencies on a known execution environment. Such an environment will expose a known set of APIs (.NET and OS APIs) and will maintain and expose expected state (e.g. Windows registry).

Developers who create plaform specific libraries can fully exploit the underlying platform. The libraries will only ever run on that given platform, making platform checks or other forms of conditional code unnecessary (modulo single sourcing code for multiple platforms).

Expand All @@ -23,9 +23,9 @@ Portable Class Libraries

Portable libraries are supported on multiple .NET platforms. They can still take dependencies on a known execution environment, however, the environment is a synthetic one that is generated by the intersection of a set of concrete .NET platforms. This means that exposed APIs and platform assumptions are a subset of what would be available to a platform-specific library.

You choose a platform configuration when you create a portable library. These are the set of platforms that you need to support (e.g. .NET Framework 4.5+, Windows Phone 8.0+). Somewhat (initially) unintuitively, the more platforms you opt to support, the fewer APIs and fewer platform assumptions you can make.
You choose a platform configuration when you create a portable library. These are the set of platforms that you need to support (e.g. .NET Framework 4.5+, Windows Phone 8.0+). The more platforms you opt to support, the fewer APIs and fewer platform assumptions you can make, the lowest common denominator. This characteristic can be confusing at first, since people often think "more is better", but find that more supported platforms results in fewer available APIs.

Many libraries have switched from producing multiple platform-specific libraries from one source (using conditional compilation directives) to portable libraries. There are several techniques for accessing platform-specific functionality within portable libraries.
Many library developers have switched from producing multiple platform-specific libraries from one source (using conditional compilation directives) to portable libraries. There are several techniques for accessing platform-specific functionality within portable libraries.

.NET Core Class Libraries
=========================
Expand All @@ -44,3 +44,7 @@ The following platforms support .NET Core class libraries:
- Windows Store Apps
- Windows Phone 8+

Mono Class Libraries
====================

Class libraries are supported on Mono, including the three types of libraries described above. Mono has often been seen (correctly) as a cross-platform implementation of the Microsoft .NET Framework. In part, this was because platform-specific .NET Framework libraries could run on the Mono runtime without modification or re-compilation. This characteristic was in place before the creation of portable class libraries, so was an obvious choice to enable binary portability between the .NET Framework and Mono (although it only worked in one direction).
86 changes: 56 additions & 30 deletions Documentation/dotnet-primer.md
Expand Up @@ -8,9 +8,9 @@ Multiple implementations of .NET are available, based on open [.NET Standards](d
Defining .NET Features
======================

There are a set of key features that together define .NET. Most of them are not unique on their own, but the peculiar aggregation of these features is what defines .NET as being distinct.
There are a set of key features that together define .NET. Most of them are not unique on their own, but the particular aggregation of these features is what defines .NET as being distinct.

- [Automatic memory management](garbage-collection.md)
- [Automatic memory management](automatic-memory-management.md)
- Verifiable code - type and memory safety
- Flexible native code compilation (enables JIT and AOT)
- Fast native interop and access to native memory
Expand All @@ -32,23 +32,6 @@ TODO: Ensure that this list is correct. Write and link to a chapter for each of

.NET includes many features and capabilities that you will use on a daily basis for common tasks and needs. You can see these described below, with examples. Some of the same topics are discussed in more detail in documents linked above.

Automatic Memory Management
---------------------------

[Garbage collection](garbage-collection.md) is the most well-known of .NET features. Developers do not need to actively manage memory, athough there are affordances to provide more information to the garbage collector (GC). C# includes the `new` keyword to allocate memory in terms of a particular type, and the `using` keyword to scope the usage of an object. The GC operates on a lazy approach to memory management, preferring application throughput to the immediate collection of memory.

The following two lines both allocate. There is no analogous keyword to de-allocate the memory. The GC reclaims the memory sometime after the two variables go out of scope.

var title = ".NET Primer";
var list = new List<string>;

Method variables normally go out of scope once a method completes, at which point they can be collected. The following example indicates to the GC that an object has gone out of scope, once the `using` statement has been completed, and the dependent `stream` object can be collected.

using(FileStream stream = GetFileStream(context))
{
//operations on the stream
}

Memory Safety
-------------

Expand All @@ -59,14 +42,14 @@ The .NET runtime provides additional services, to complete the promise of memory
The following example will throw as a result of memory safety.

int[] numbers = new int[42];
int number = numbers[42] // will throw (indexes are 0-based)
int number = numbers[42]; // will throw (indexes are 0-based)

Type Safety
-----------

Objects are allocated in terms of types. The only operations allowed for a given object, and the memory it consumes, are those of its type. A `Dog` type may have `Jump` and `WagTail` methods, but not likely a `SumTotal` method. A program can only call the declared methods of a given type. All other calls will result in an exception.

.NET languages can be object-oriented, with hiearchies of base and derived classes. The .NET runtime will only allow object casts and calls that align with the object hierarchy.
.NET languages can be object-oriented, with hierarchies of base and derived classes. The .NET runtime will only allow object casts and calls that align with the object hierarchy.

Dog dog = Dog.AdoptDog();
Pet pet = (Pet)dog; // Dog derives from Pet
Expand Down Expand Up @@ -97,31 +80,74 @@ The most commonly used generic type is `List<T>` and its sibling `Dictionary<K,V
Async Programming
-----------------

Async is a first-class concept within .NET, with async support in the runtime, the framework libraries and various .NET languages. Async is based off of the `Task` concept, which encaptsulates a set of operations to be completed. Tasks are distinct from threads and may not rely on threads or require CPU time much at all, particularly for i/o-bound tasks.
Async is a first-class concept within .NET, with async support in the runtime, the framework libraries and various .NET languages. Async is based off of the `Task` concept, which encapsulates a set of operations to be completed. Tasks are distinct from threads and may not rely on threads or require CPU time much at all, particularly for i/o-bound tasks.

TODO: Elaborate on Task concept.

C# includes special treatment for async, including the special keyword `await` for managing tasks. The following example demonstrates calling a web service as an async operation.

string url = "http://someUrl";
HttpClient client = new HttpClient();
string json = await client.GetStringAsync(url);

The call to `client.GetStringAsync(url)` does not block, but instead immediately yields by returing a `Task`. Computation resumes and the call returns the requested string when the network activity has completed.
The call to `client.GetStringAsync(url)` does not block, but instead immediately yields by returning a `Task`. Computation resumes and the call returns the requested string when the network activity has completed.

Language Integrated Query (Linq)
Language Integrated Query (LINQ)
--------------------------------

.NET programs typically operate on some form of data. The data can be database-resident or in the form of objects (sometimes called POCOs - "Plain Old CLR Objects"). Linq provides a language-integrated uniform query model over data, independent of the source. Linq providers bridge the gap between the uniform query model and the form of the data, such as SQL Server tables.
.NET programs typically operate on some form of data. The data can be database-resident or in the form of objects (sometimes called POCOs - "Plain Old CLR Objects"). LINQ provides a language-integrated uniform query model over data, independent of the source. Linq providers bridge the gap between the uniform query model and the form of the data, such as SQL Server tables, XML documents, standard collections like List<T> and more.

The follow examples demonstrate various uses of Linq to query different forms of data.
The follow examples demonstrate various uses of LINQ to query different forms of data.

TODO: Examples.

Lambdas
-------
Delegates and Lambdas
---------------------

Delegates are like C++ function pointers, but are type safe. They are a kind of disconnected method within the CLR type system. Regular methods are attached to a class and only directly callable through static or instance calling conventions. Alternatively, delegates can be thought of as a one method interface, without the interface.

Delegates define a type, which specify a particular method signature. A method (static or instance) that satisfies this signature can be assigned to a variable of that type, then called directly (with the appropriate arguments) or passed as an argument itself to another method and then called. The following example demonstrates delegate use.

public delegate string Reverse(string s);

static string ReverseString(string s)
{
return new string(s.Reverse().ToArray());
}

static void Main(string[] args)
{
Reverse rev = ReverseString;

Console.WriteLine(rev("a string"));
}

.NET include a set of pre-defined delegate types - Func<> and Action<> - that be used in many situations, without the requirement to define new types. The example above can be re-written to no longer defined the reverse delegate and instead define the rev variable as a Func<string,string>. The program will function the same.

Func<string,string> rev = ReverseString;

Lambdas are a more convenient syntax for using delegates. They declare a signature and a method body, but don't have an formal identity of their own, unless they are assigned to a delegate. Unlike delegates, they can be directly assigned as the left-hand side of event registration or as a Linq select clause.

You can see the use of lambda as a linq select clause in the Linq section above. The following example rewrites the program above using the more compact lambda syntax. Note that an explictly defined delegate could still be used, instead of Func<>.

static void Main(string[] args)
{
Func<string,string> rev = (s) => {return new string(s.Reverse().ToArray());};

Console.WriteLine(rev("a string"));
}

The following example demonstrated the use of a lambda as an event handler.

Lambdas are a kind of mini-method. They declare a signature and a method body, but don't have an identity of their own, like a method on a type. They can however, be assigned to a variable and be called, with the appropriate arguments, and passed in a method signature. They are effectively an alternative delegate syntax. Unlike delegates, they can be directly assigned as the left-hand side of event registration or as a Linq select clause.
public MainWindow()
{
InitializeComponent();

The following example demonstrated the use of a lambda as an event handler. You can see the use of lambda as a linq select clause in the Linq section above.
Loaded += (o, e) =>
{
this.Title = "Loaded";
};
}

Native Interop
--------------
Expand Down
Binary file added Documentation/images/assembly-headers.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 60ab41f

Please sign in to comment.