Saturday, December 29, 2012

Pro C#4

1. Delegate, Event and Lamda
When the compiler processes the event keyword, you are
automatically provided with registration and unregistration methods as well as any necessary member
variables for your delegate types. These delegate member variables are always declared private, and
therefore they are not directly exposed from the object firing the event. To be sure, the event keyword is
little more than syntactic sugar in that it simply saves you some typing time.

Defining an event is a two-step process. First, you need to define a delegate type that will hold the
list of methods to be called when the event is fired. Next, you declare an event (using the C# event
keyword) in terms of the related delegate type.
public delegate void CarEngineHandler(string msg);
// This car can send these events.
public event CarEngineHandler Exploded;
public event CarEngineHandler AboutToBlow;

// Register event handlers.
c1.AboutToBlow += CarIsAlmostDoomed;
c1.AboutToBlow += CarAboutToBlow;
c1.Exploded += CarExploded;

Anonymous Methods
// Register event handlers as anonymous methods.
c1.AboutToBlow += delegate
{
Console.WriteLine("Eek! Going too fast!");
};
c1.Exploded += delegate(object sender, CarEventArgs e)
{
Console.WriteLine("Fatal Message from Car: {0}", e.msg);
};
Anonymous methods are interesting in that they are able to access the local variables of the method that
defines them. Formally speaking, such variables are termed outer variables of the anonymous method.
Lambda expressions are nothing more than a very concise way to author
anonymous methods and ultimately simplify how we work with the .NET delegate type.
// Now, use an anonymous method.
List<int> evenNumbers = list.FindAll(delegate(int i)
{ return (i % 2) == 0; } );
// Now, use a C# lambda expression.
List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);
lambda expressions can be used anywhere
you would have used an anonymous method or a strongly typed delegate (typically with far fewer
keystrokes).
Under the hood, the C# compiler translates the expression into a standard anonymous
method.
A lambda expression is written by first defining a parameter list, followed by the => token (C#’s token for
the lambda operator found in the lambda calculus), followed by a set of statements (or a single
statement) that will process these arguments. From a very high level, a lambda expression can be
understood as follows:
ArgumentsToProcess => StatementsToProcessThem
// Now, explicitly state what the parameter type.
List<int> evenNumbers = list.FindAll((int i) => (i % 2) == 0);
// My list of parameters (in this case a single integer named i)
// will be processed by the expression (i % 2) == 0.
List<int> evenNumbers = list.FindAll((i) => ((i % 2) == 0));
SimpleMath m = new SimpleMath();
m.SetMathHandler((msg, result) =>
{Console.WriteLine("Message: {0}, Result: {1}", msg, result);});
// Hook into events with lambdas!
c1.AboutToBlow += (sender, e) => { Console.WriteLine(e.msg);};
c1.Exploded += (sender, e) => { Console.WriteLine(e.msg); };

2. Linq

In a nutshell, extension methods allow
existing compiled types (specifically, classes, structures, or interface implementations) as well as types
currently being compiled (such as types in a project that contains extension methods) to gain new
functionality without needing to directly update the type being extended.
When you define extension methods, the first restriction is that they must be defined within a static
class (see Chapter 5), and therefore each extension method must be declared with the static keyword.
The second point is that all extension methods are marked as such by using the this keyword as a
modifier on the first (and only the first) parameter of the method in question. The third point is that
every extension method can be called either from the correct instance in memory or statically via the
defining static class!
Given this flavor of syntactic sugar, it is really important to point out that unlike a
“normal” method, extension methods do not have direct access to the members of the type they are
extending; said another way, extending is not inheriting.

The Language Integrated Query (LINQ) technology set, introduced initially
in .NET 3.5, provides a concise, symmetrical, and strongly typed manner to access a wide variety of data
stores.
From a very high level, LINQ can be understood as a strongly typed query language, embedded directly
into the grammar of C# itself. Using LINQ, you can build any number of expressions which have a lookand-
feel similar to that of a database SQL query. However, a LINQ query can be applied to any number
of data stores, including stores that have nothing to do with a literal relational database.
           string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};

IEnumerable<string> subset = from game in currentVideoGames
where game.Contains(" ") orderby
game select game;

Another important point regarding LINQ query expressions is that they are not actually evaluated until
you iterate over the sequence. Formally speaking, this is termed deferred execution. The benefit of this
approach is that you are able to apply the same LINQ query multiple times to the same container, and
rest assured you are obtaining the latest and greatest results.

int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
// Get data RIGHT NOW as int[].
int[] subsetAsIntArray =
(from i in numbers where i < 10 select i).ToArray<int>();
// Get data RIGHT NOW as List<int>.
List<int> subsetAsListOfInts =
(from i in numbers where i < 10 select i).ToList<int>();

// Extract the ints from the ArrayList.
ArrayList myStuff = new ArrayList();
myStuff.AddRange(new object[] { 10, 400, 8, false, new Car(), "string data" });
var myInts = myStuff.OfType<int>();

It is also possible to project new forms of data from an existing data source.
var nameDesc = from p in products select new { p.Name, p.Description };
// Get count from the query.
int numb =
(from g in currentVideoGames where g.Length > 6 select g).Count<string>();
The Enumerable class supports a set of extension methods which allows you to use two (or more) LINQ
queries as the basis to find unions, differences, concatenations, and intersections of data. First of all,
consider the Except() extension method, which will return a LINQ result set that contains the
differences between two containers, which in this case, is the value “Yugo”:
List<string> myCars = new List<String> {"Yugo", "Aztec", "BMW"};
List<string> yourCars = new List<String>{"BMW", "Saab", "Aztec" };
var carDiff =(from c in myCars select c)
.Except(from c2 in yourCars select c2);
The Intersect() method will return a result set that contains the common data items in a set of
containers.
The Union() method, as you would guess, returns a result set that includes all members of a batch of
LINQ queries.
Finally, the Concat()extension method returns a result set that is a direct concatenation of LINQ
result sets.
simply call the Distinct() extension method to remove duplicate entries.
static void DisplayConcatNoDups()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
var carConcat = (from c in myCars select c)
.Concat(from c2 in yourCars select c2);
// Prints:
// Yugo Aztec BMW Saab Aztec.
foreach (string s in carConcat.Distinct())
Console.WriteLine(s);
}

LINQ queries can also be designed to perform various aggregation operations on the result set. The
Count() extension method is one such aggregation example. Other possibilities include obtaining an
average, max, min, or sum of values using the Max(), Min(), Average(), or Sum() members of the
Enumerable class.

// Build a query expression using extension methods
// granted to the Array via the Enumerable type.
var subset = currentVideoGames.Where(game => game.Contains(" "))
.OrderBy(game => game).Select(game => game);

3.
Simply put, an
assembly is a versioned, self-describing binary file hosted by the CLR.
Regardless of how a code library is packaged, the .NET platform allows you to reuse types in a
language-independent manner. For example, you could create a code library in C# and reuse that library
in any other .NET programming language.

.NET assemblies are assigned a four-part numerical version number of the form
<major>.<minor>.<build>.<revision>. (If you do not explicitly provide a version number, the assembly is
automatically assigned a version of 1.0.0.0, given the default Visual Studio project settings.) This
number, in conjunction with an optional public key value, allows multiple versions of the same assembly
to coexist in harmony on a single machine. Formally speaking, assemblies that provide public key
information are termed strongly named.
a manifest is a blob of metadata that describes the assembly itself (name, version, required external
assemblies, etc.).
In addition to manifest data, an assembly contains metadata that describes the composition
(member names, implemented interfaces, base classes, constructors, and so forth) of every contained
type. Because an assembly is documented in such detail, the CLR does not consult the Windows system
registry to resolve its location (quite the radical departure from Microsoft’s legacy COM programming
model).
Structurally speaking, a .NET assembly
(*.dll or *.exe) consists of the following elements:
• A Windows file header
• A CLR file header
• CIL code
• Type metadata
• An assembly manifest
• Optional embedded resources

As a naming convention, the secondary modules in a multifile assembly take a *.netmodule file
extension; however, this is not a requirement of the CLR. Secondary *.netmodules also contain CIL code
and type metadata, as well as a module-level manifest, which simply records the externally required
assemblies of that specific module.
The major benefit of constructing multifile assemblies is that they provide a very efficient way to
download content.
Another benefit of multifile assemblies is that they enable modules to be authored using multiple
.NET programming languages (which is very helpful in larger corporations, where individual
departments tend to favor a specific .NET language).
a majority of the attributes in AssemblyInfo.cs will be used to update the .custom
token values within an assembly MANIFEST.
Notice that when you are referencing a multifile assembly, the compiler needs to be supplied only
with the name of the primary module (the *.netmodules are loaded on demand by the CLR when used by
the client’s code base).
Private assemblies must be located within the same directory as the client application
that’s using them (the application directory) or a subdirectory thereof.
In either case, the CLR extracts the friendly name of the assembly and begins probing the client’s
application directory for a file named CarLibrary.dll. If this file cannot be located, an attempt is made
to locate an executable assembly based on the same friendly name (for example, CarLibrary.exe). If
neither file can be located in the application directory, the runtime gives up and throws a
FileNotFoundException exception at runtime.
Technically speaking, if a copy of the requested assembly cannot be found within the client’s application
directory, the CLR will also attempt to locate a client subdirectory with the exact same name as the assembly’s
friendly name (e.g., C:\MyClient\CarLibrary). If the requested assembly resides within this subdirectory, the CLR
will load the assembly into memory.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MyLibraries"/>
</assemblyBinding>
</runtime>
</configuration>

the privatePath attribute cannot be used to specify an absolute (C:\SomeFolder\
SomeSubFolder) or relative (..\\SomeFolder\\AnotherFolder) path! If you wish to specify a directory outside
the client’s application directory, you will need to use a completely different XML element named <codeBase>
Multiple subdirectories can be assigned to the privatePath attribute using a semicolon-delimited
list.
<probing privatePath="MyLibraries;MyLibraries\Tests"/>

Using this approach, all you need to do is maintain App.config, and Visual Studio 2010 will ensure
your application directory contains the latest and greatest configuration data (even if you happen to
rename your project).
You cannot install executable assemblies (*.exe) into the GAC. Only assemblies that take the *.dll file
extension can be deployed as a shared assembly.
Before you can deploy an assembly to the GAC, you must assign it a strong name, which is used to
uniquely identify the publisher of a given .NET binary.
To provide a strong name for an assembly, your first step is to generate public/private key data
using the .NET Framework 4.0 SDK’s sn.exe utility
Once the C# compiler is
made aware of the location of your *.snk file, it will record the full public key value in the assembly
manifest using the .publickey token at the time of compilation.
At compile time, a digital signature is generated and embedded into the assembly based in
part on public and private key data

sn -k MyTestKeyPair.snk
[assembly: AssemblyKeyFile(@"C:\MyTestKeyPair\MyTestKeyPair.snk")]
gacutil -i CarLibrary.dll

view your installed CarLibrary in the GAC, simply by
navigating to C:\Windows\assembly.
With the release of .NET 4.0, the GAC has been split in two. Specifically, under C:\Windows\assembly
you will find the location of the .NET 1.0-.NET 3.5 base class libraries
However, when you compile an assembly
under .NET 4.0, and deploy it to the GAC using gacutil.exe, your library will be deployed to a brandnew
location: C:\Windows\Microsoft.NET\assembly\GAC_MSIL.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="CarLibrary"
publicKeyToken="33A2BC294331E8B9"
culture="neutral"/>
<bindingRedirect "1.0.0.0-1.2.0.0"
newVersion= "2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>


The <codeBase> element can be used to
instruct the CLR to probe for dependent assemblies located at arbitrary locations (such as network end
points, or an arbitrary machine path outside a client’s application directory).
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name=" CarLibrary" publicKeyToken="33A2BC294331E8B9" />
<codeBase version="2.0.0.0" href="file:///C:/MyAsms/CarLibrary.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

The System.Configuration namespace provides a small set of types you can use to read custom data
from a client’s *.config file. These custom settings must be contained within the scope of an
<appSettings> element. The <appSettings> element contains any number of <add> elements that define
key/value pairs to be obtained programmatically.
<configuration>
<appSettings>
<add key="TextColor" value="Green" />
<add key="RepeatCount" value="8" />
</appSettings>
</configuration>
AppSettingsReader ar = new AppSettingsReader();
int numbOfTimes = (int)ar.GetValue("RepeatCount", typeof(int));
string textColor = (string)ar.GetValue("TextColor", typeof(string));
Console.ForegroundColor =
(ConsoleColor)Enum.Parse(typeof(ConsoleColor), textColor);

4. Reflection
// Obtain type information using a SportsCar instance.
SportsCar sc = new SportsCar();
Type t = sc.GetType();
The next way to obtain type information is using the C# typeof operator:
// Get the Type using typeof.
Type t = typeof(SportsCar);
To obtain type information in a more flexible manner, you may call the static GetType()
Type t = Type.GetType("CarLibrary.SportsCar", false, true);
when you wish to obtain metadata for a type within an external
private assembly, the string parameter is formatted using the type’s fully qualified name, followed by a
comma, followed by the friendly name of the assembly containing the type:
// Obtain type information for a nested enumeration
// within the current assembly.
Type t = Type.GetType("CarLibrary.JamesBondCar+SpyOptions");

// Obtain type information for a type within an external assembly.
Type t = Type.GetType("CarLibrary.SportsCar, CarLibrary");

Formally speaking, the act of loading external assemblies on demand is known as a dynamic load.
the static Assembly.Load() method has been passed only the friendly name of the
assembly you are interested in loading into memory.
If you wish to make ExternalAssemblyReflector more flexible, you can update your code to load the
external assembly using Assembly.LoadFrom() rather than Assembly.Load()
Essentially, Assembly.LoadFrom() allows you to programmatically supply a
<codeBase> value. With this adjustment, you can now pass in a full path to your console application.
Simply put, late binding is a technique in which you are able to create an instance of a given type and
invoke its members at runtime without having hard-coded compile-time knowledge of its existence.
The System.Activator class (defined in mscorlib.dll) is the key to the .NET late binding process.
// Get metadata for the Minivan type.
Type miniVan = asm.GetType("CarLibrary.MiniVan");
// Create the Minivan on the fly.
object obj = Activator.CreateInstance(miniVan);
// Get info for TurboBoost.
MethodInfo mi = miniVan.GetMethod("TurboBoost");
// Invoke method ('null' for no parameters).
mi.Invoke(obj, null);
// Invoke TurnOnRadio() with arguments.
MethodInfo mi = sport.GetMethod("TurnOnRadio");
mi.Invoke(obj, new object[] { true, 2 });
In a nutshell, attributes are nothing more than code annotations that can be
applied to a given type (class, interface, structure, etc.), member (property, method, etc.), assembly, or
module.
.NET attributes are class types that extend the abstract System.Attribute base class.
Understand that when you apply attributes in your code, the embedded metadata is essentially
useless until another piece of software explicitly reflects over the information. If this is not the case, the
blurb of metadata embedded within the assembly is ignored and completely harmless.
if the C# compiler encounters
the [CLSCompliant] attribute, it will automatically check the attributed item to ensure it is exposing only
CLS-compliant constructs. By way of another example, if the C# compiler discovers an item attributed
with the [Obsolete] attribute, it will display a compiler warning in the Visual Studio 2010 Error List
window.
By doing so, you are essentially able to
create a set of “keywords” that are understood by a specific set of assemblies.
If you were consulting the .NET Framework 4.0 SDK documentation, you may have noticed that the
actual class name of the [Obsolete] attribute is ObsoleteAttribute, not Obsolete. As a naming
convention, all .NET attributes (including custom attributes you may create yourself) are suffixed with
the Attribute token. However, to simplify the process of applying attributes, the C# language does not
require you to type in the Attribute suffix.
See Chapter 2 for an explication of using code snippets.
It is also possible to apply attributes on all types within a given module (for a multi-file assembly; see
Chapter 14) or all modules within a given assembly using the [module:] and [assembly:] tags,
respectively. For example, assume you wish to ensure that every public member of every public type
defined within your assembly is CLS compliant.
// Get a Type representing the Winnebago.
Type t = typeof(Winnebago);
// Get all attributes on the Winnebago.
object[] customAtts = t.GetCustomAttributes(false);
Simply put, if the extendable application has been preprogrammed to query for specific interfaces,
it is able to determine at runtime whether the type can be activated.
In a nutshell, application domains (or simply AppDomains) are logical subdivisions within a given
process that host a set of related .NET assemblies. As you will see, an AppDomain is further subdivided
into contextual boundaries, which are used to group together like-minded .NET objects.
using too many
threads in a single process can actually degrade performance, as the CPU must switch between the active
threads in the process (which takes time).
Under the .NET platform, executables are not hosted directly within a Windows process, as is the case in
traditional unmanaged applications. Rather, a .NET executable is hosted by a logical partition within a
process termed an application domain.
While a single process may host multiple AppDomains, this is not typically the case.
Select Events of the AppDomain Type
UnhandledException Occurs when an exception is not caught by an exception handler.
Recall that when a .NET executable starts, the CLR will automatically place it into the default app
domain o f the hosting process. This is done automatically and transparently, and you never have to
author any specific code to do so. However, it is possible for your application to gain access to this
default application domain using the static AppDomain.CurrentDomain property. Once you have this
access point, you are able to hook into any events of interest, or make use of the methods and properties
of AppDomain to perform some runtime diagnostics.
As you have just seen, AppDomains are logical partitions within a process used to host .NET assemblies.
On a related note, a given application domain may be further subdivided into numerous context
boundaries. In a nutshell, a .NET context provides a way for a single AppDomain to establish a “specific
home” for a given object.

5. CIL
Directives are represented syntactically using a single dot (.) prefix (e.g., .namespace, .class,
.publickeytoken, .method, .assembly, etc.).
In many cases, CIL directives in and of themselves are not descriptive enough to fully express the
definition of a given .NET type or type member. Given this fact, many CIL directives can be further
specified with various CIL attributes to qualify how a directive should be processed. For example, the
.class directive can be adorned with the public attribute (to establish the type visibility),
Thankfully, for each binary opcode of CIL, there is a corresponding mnemonic. For example, the add
mnemonic can be used rather than 0X58, sub rather than 0X59, and newobj rather than 0X73. Given this
opcode/mnemonic distinction, realize that CIL decompilers such as ildasm.exe translate an assembly’s
binary opcodes into their corresponding CIL mnemonics.
Formally speaking, the entity used to hold a set of values to be evaluated is termed the virtual
execution stack. As you will see, CIL provides a number of opcodes that are used to push a value onto the
stack; this process is termed loading. As well, CIL defines a number of additional opcodes that transfer
the topmost value on the stack into memory (such as a local variable) using a process termed storing.
A dynamic assembly, on the other hand, is created in memory on the fly using the types provided by
the System.Reflection.Emit namespace. The System.Reflection.Emit namespace makes it possible to
create an assembly and its modules, type definitions, and CIL implementation logic at runtime. Once
you have done so, you are then free to save your in-memory binary to disk. This, of course, results in a
new static assembly.
With the release of .NET 4.0, the C# language now supports a new keyword named dynamic.
As far as the C# compiler is concerned, a data point declared with the dynamic keyword can be
assigned any initial value at all, and can be reassigned to any new (and possibly unrelated) value during
its lifetime.
dynamic t = "Hello!";
Console.WriteLine("t is of type: {0}", t.GetType());
t = false;
Console.WriteLine("t is of type: {0}", t.GetType());
t = new List<int>();
Console.WriteLine("t is of type: {0}", t.GetType());
the previous code would compile and
execute identically if you were to declare the t variable as a System.Object. However, as you will soon
see, the dynamic keyword offers many additional features.
The var keyword
can never be used as a return value, a parameter or a member of a class/structure. This is not the case
with the dynamic keyword however.
a dynamic data item cannot make
use of lambda expressions or C# anonymous methods when calling a method.
Given the fact that dynamic data is not strongly typed, not checked at compile time, has no ability to
trigger IntelliSense and cannot be the target of a LINQ query, you are absolutely correct to assume that
using the dynamic keyword just for the sake of doing so is very poor programming practice.
However, in a few circumstances, the dynamic keyword can radically reduce the amount of code
you need to author by hand. Specifically, if you are building a .NET application which makes heavy use
of late binding (via reflection), the dynamic keyword can save you typing time. As well, if you are building
a .NET application that needs to communicate with legacy COM libraries (such as Microsoft Office
products), you can greatly simplify your codebase via the dynamic keyword.
With
the release of .NET 4.0, the Common Language Runtime (CLR) has a complementary runtime
environment named the Dynamic Language Runtime (DLR).
The role of the DLR is to enable various dynamic languages to run with the .NET runtime and give
them a way to interoperate with other .NET code. Two popular dynamic languages which make use of
the DLR are IronPython and IronRuby.
With the release of .NET 4.0, Microsoft introduced the System.Dynamic namespace within the
System.Core.dll assembly. Truth be told, the chances that you will need to ever directly use the types
within this namespace are slim to none. However, if you were a language vendor, who wanted to enable
their dynamic languages to interact with the DLR, you could make use of System.Dynamic namespace to
build a custom runtime binder.
// Get metadata for the SimpleMath type.
Type math = asm.GetType("MathLibrary.SimpleMath");
// Create a SimpleMath on the fly.
dynamic obj = Activator.CreateInstance(math);
Console.WriteLine("Result is: {0}", obj.Add(10, 70));

7. Thread.
there
are very few operations in the .NET base class libraries that are guaranteed to be atomic. Even the act of
assigning a value to a member variable is not atomic! Unless the .NET Framework 4.0 SDK documentation
specifically says an operation is atomic, you must assume it is thread-volatile and take precautions.
Aborting or suspending an active thread is generally considered a bad idea. When you do so, there is a
chance (however small) that a thread could “leak” its workload when disturbed or terminated.
In most cases, you will seldom (if ever) need to directly alter a thread’s priority level. In theory, it is
possible to jack up the priority level on a set of threads, thereby preventing lower-priority threads from
executing at their required levels (so use caution).
Background threads (sometimes called daemon threads) are viewed by the CLR as
expendable paths of execution that can be ignored at any point in time (even if
they are currently laboring over some unit of work). Thus, if all foreground threads
have terminated, any and all background threads are automatically killed when
the application domain unloads.
Starting with .NET 4.0, use of the TPL is the recommended way to build multithreaded applications.

No comments:

Post a Comment