C# 6 and .NET Core 1.0:Modern Cross:Platform Development
上QQ阅读APP看书,第一时间看更新

Using assemblies and namespaces

The .NET Framework and the .NET Core are made up of several pieces, which are as follows:

  • Language compilers: These turn your source code (written with languages such as C#, F#, Visual Basic, and others) into intermediate language (IL) code stored in assemblies (applications and class libraries). C# 6 introduced a completely rewritten compiler known as Roslyn.
  • Common Language Runtimes (CLR and CoreCLR): These runtimes load assemblies, compile the IL code stored in them into native code instructions for your computer's CPU, and execute the code within an environment that manages resources such as threads and memory.
  • Base Class Libraries (BCL and CoreFX): These are prebuilt assemblies of types for performing common tasks when building applications. You can use them to quickly build anything you want, rather like combining LEGO pieces.

Comparing .NET Framework with .NET Core

The .NET Framework is a superset of .NET Core.

Although .NET Core has less functionality today, going forward, Microsoft has said that new features will be first added to .NET Core and then ported back to .NET Framework.

In this book, I will use the term .NET when introducing features that apply to both the .NET Framework and the .NET Core.

Base Class Libraries and CoreFX

The .NET Framework's BCL and the .NET Core's CoreFX are libraries of prebuilt code that are pided into assemblies and namespaces that make it easier to manage the tens of thousands of types available. It is important to understand the difference between an assembly and a namespace.

Assemblies

An assembly is where a type is stored in the filesystem. Assemblies are a mechanism for deploying code. For example, the System.Data.dll assembly contains types for managing databases.

When using the .NET Framework, the System.Data.dll assembly can be found in the Global Assembly Cache (GAC) centralized folder C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\.

When using .NET Core, the equivalent assembly would be found in a private subfolder alongside other dependency assemblies.

Namespaces

A namespace is the address of a type. Namespaces are a mechanism to uniquely identify a type by providing a full address rather than just a short name.

In the real world, Bob of 34 Sycamore Street is different from Bob of 12 Willow Drive.

In .NET, the IActionFilter interface of the System.Web.Mvc namespace is different from the IActionFilter interface of the System.Web.Http.Filters namespace.

Referencing an assembly

If an assembly is compiled as a class library (it provides types for other assemblies to use), then it has the file extension DLL (dynamic link library) and cannot be executed standalone.

If an assembly is compiled as an application, then it has the file extension EXE (executable) and can be executed standalone.

Any assembly (both applications and class libraries) can reference one or more class library assemblies, but you cannot have circular references, so assembly B cannot reference assembly A if assembly A already references assembly B. Visual Studio will warn you if you attempt to add a reference that would cause a circular reference.

Referencing Microsoft Core Library

Every application compiled for .NET has an automatic reference to Microsoft Core Library (mscorlib.dll). This special assembly contains types that almost all applications would need, such as the int and string types.

Tip

The name Microsoft Core Library has nothing to do with .NET Core.

To use types in other assemblies, they must be manually referenced. Most Visual Studio project templates add some common assembly references for you, for example, the System.Xml.dll assembly for working with XML.

An example of assembly references

The following diagram shows a console application that needs to connect to a database, process an XML file, connect to an HTTP server, and query data using LINQ so that it has references to the assemblies that contain types to perform those tasks:

Relating assemblies and namespaces

The following steps will help you to relate assemblies and namespaces:

  1. Start Microsoft Visual Studio 2015.
  2. In Visual Studio, press Ctrl + Shift + N or navigate to File | New | Project….
  3. In the New Project dialog, in the Installed Templates list, select Visual C#. In the list at the center, select Console Application, type the name Ch04_AssembliesAndNamespaces, change the location to C:\Code, type the solution name Chapter04, and then click on OK.
  4. In the Solution Explorer window, expand References. Note that a console application project already has references to several assemblies, including System.Xml.

    If you don't need any of these assemblies, then you can remove the reference by selecting it and pressing Del, or right-clicking and choosing Remove:

  5. Inside the Main method, type the following code:
    var doc = new XmlDocument();

    The XmlDocument type is not recognized because we have not told the compiler what the namespace of the type is. Although this project already has a reference to the assembly that contains the type, we also need to either prefix the type name with its namespace, or import the namespace. We can get Visual Studio to fix this problem for us.

Importing a namespace

You need to perform the following steps to import a namespace:

  1. Click inside the XmlDocument type. Visual Studio displays a light bulb showing that it recognizes the type and can automatically fix the problem for you, as shown in the following screenshot:
  2. Click on the light bulb or press Ctrl+.
  3. Choose using System.Xml; from the menu showing several other options as well. This will import the namespace by adding a using statement to the top of the file:

Once a namespace is imported for a code file, then all the types within the namespace are available for use in that code file just by typing their name.

Add another line of code to create an XmlDataDocument instance:

var data = new XmlDataDocument();
Note

You will see a green squiggle under the type name, which is a warning telling us that this type is obsolete and will be removed in a future release. Ignore that because it's not relevant to what you are learning now. As long as a type name is teal (bluish-green) it means the compiler understands it.

In the Solution Explorer window, inside References, right-click on System.Xml, and choose Remove.

After a few seconds, Visual Studio displays a red squiggle under XmlDocument, as shown in the following screenshot, and the text turns black instead of teal. This indicates that Visual Studio doesn't recognize the XmlDocument type:

This is because we no longer have a reference to the assembly that contains the XmlDocument type. Just having the import statement (using System.Xml;) is not enough to find the type.

Tip

The color syntax highlighting behavior may be different in older versions of Visual Studio.

However, the XmlDataDocument type is not affected (it is still teal). This is because XmlDataDocument is not in the System.Xml assembly. It is actually in the System.Data assembly and our project still has a reference to that assembly.

Tip

A type can be in any assembly and any namespace. They do not have to be related. It is up to the creator of a type to decide what makes most sense for the type. For example, the Microsoft employee who was responsible for the XmlDataDocument type decided that it should be stored in the System.Data assembly but logically grouped with types in the System.Xml namespace.

The following table summarizes the assembly and namespace locations of the two types that we have been looking at:

To fix the current compile error, we need to add back the reference to the System.Xml assembly.

In the Solution Explorer window, right-click on References, choose Add Reference…, and in the Reference Manager dialog box that appears, select Assemblies on the left-hand side, scroll down through the list, select the checkbox next to System.Xml, and then click on OK:

Browsing assemblies and namespaces

A useful tool for understanding the relationship between assemblies and namespaces is the Object Browser.

On the View menu, choose Object Browser, or press Ctrl + W, J.

Note

Remember that keyboard shortcuts are dependent upon your settings. If you have chosen an option other than Visual C# for your development settings, then your keyboard shortcut for the Object Browser window may be different!

The Object Browser window shows that inside the System.Data assembly is the namespace System.Xml, and that contains the XmlDataDocument type:

If you expand the System.Xml assembly, you will see that it adds far more types to the System.Xml namespace.

If you select an assembly, you will see its location in the file system, for example, C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\System.Xml.dll:

Tip

Best Practice

Use class library assemblies to group together types with related functionality. Carefully consider the namespace that your types should belong to. Although Microsoft puts all .NET types underneath the System namespace, they often put other types underneath a Microsoft.ApplicationName namespace. You should follow their example and therefore use your organization name and application names. For example, Packt.Publishing might be a good namespace for a Book type.

Relating C# keywords to .NET types

One of the common questions I get from new C# programmers is, "What is the difference between string with a lowercase and String with an uppercase?"

The short answer is easy: none.

The long answer is that all C# type keywords are aliases for a .NET type in a class library assembly.

When you use the keyword string, the compiler turns it into a System.String type. When you use the type int, the compiler turns it into a System.Int32 type. You can even see this if you hover your mouse over an int type, as follows:

Tip

Best Practice

Use the C# keyword instead of the actual type because the keywords do not need the namespace imported.

The following table shows the 16 C# type keywords and their actual .NET types:

Tip

Other .NET programming language compilers can do the same thing. For example, the Visual Basic .NET language has a type named Integer that is its alias for System.Int32.