0% found this document useful (0 votes)
245 views

C

curs c#

Uploaded by

Adriana Popescu
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
245 views

C

curs c#

Uploaded by

Adriana Popescu
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 242

C#

Piteti University University of Bucharest Spiru Haret University

The Development Platform: the Microsoft .NET Framework

The .NET Framework consists of two parts:

the common language runtime (CLR) file loader, garbage collector), security system (code access security), and so on. Framework Class Library (FCL).

History

The principal inventors: Anders Hejlsberg, Scott Wiltamuth, Peter Golde ECMA Technical Committee 39 (TC39) Task Group 2(TG2) is responsible for the standardization of the language

Turbo Pascal Delphi (designed by Anders Hejlsberg)

C++

Objective C Java C# (year 2000)

Modula

C#: the native language of .NET Framework


Common Language Runtime (common run time environment for memory management, security, robust error-handling, basic I/O) Class Library
(threading, file i/o, database, XML parsing, data structures (stacks etc.))

VS.NET IDE for GUI development W2K, WXP, W2K3 .NET SDK Command line tools GUI help W2K, WXP, W2K3 .NET Runtime

Namespaces:
System.Web, System.Windows.Forms, System (Runtime,Threading, IO etc.), System.Data (ADO, SQL etc.), System.XML, System.Drawing

.NET Programming Languages or compatible (C#, Visual C++, Visual Basic .NET, Java Script .NET, COBOL, Perl etc.) Active Server Pages .NET environment
-MS ASP enable the creation of dynamic pages based on user input and interaction with a Web site (by scripting) -ASP.NET -code-behind: the code and HTML can be separated -supports Web Forms. -uses the just-in-time (JIT) compiler.

W28, WNT, W2K,WXP

NET Compact

Mobile devices

Compiling a .Net compatible language


>csc /help or >csc /? for Compiler Options

Portability Efficiency

(bad) (good)
Java program Java compiler C# program C# compiler (csc)

C/C++ program C/C++ compiler for machine A

VB program VB compiler

Another machine

Java machine- free intermediate code (byte code) Java virtual machine for A

Language free and machine- free intermediate code (MSIL)+ Metadata

(persistent)Code for machine A

Another machine

JIT compiler for A (first run) (volatile)Code for machine A Runtime environment machine A (subsequent runs) results

Another machine

Runtime environment machine A results

Runtime environment machine A results

JIT= Just In Time compilation; MSIL=MicroSoft Intermediate Language

C# and Java

Below is a list of features C# and Java share, which are intended to improve on C++. [1]

Compiles into machine-independent language-independent code which runs in a managed execution environment. Garbage Collection coupled with the elimination of pointers (in C# restricted use is permitted within code marked unsafe) Powerful reflection capabilities No header files, all code scoped to packages or assemblies, no problems declaring one class before another with circular dependencies Classes all descend from object and must be allocated on the heap with new keyword Thread support by putting a lock on objects when entering code marked as locked/synchronized Interfaces, with multiple-inheritance of interfaces, single inheritance of implementations Inner classes No concept of inheriting a class with a specified access level No global functions or constants, everything belongs to a class Arrays and strings with lengths built-in and bounds checking The "." operator is always used, no more ->, :: operators null and boolean/bool are keywords All values are initialized before use Can't use integers to govern if statements Try Blocks can have a finally clause

Hello, World; Generating XML documentation from comments


// Comments and embeded documentation in C# /* This is a comment * that continues * across lines */ using System; ///This is a class containing the entry point of the application public class Hi{ /// The entry point is named <c>Main</c> /// It has no parameter public static void Main(){ /// Wrong place for an XML comment Console.WriteLine(Hello, world); Console.ReadLine(); } } /// Wrong place for an XML comment

(1/2)

// this is a C++ one-line comment

/*traditional C-style Multi-lines comment that was inherited by C++*/

/// C# single line documentation (or XML) comment /// Must be placed on a valid language element /// useful to maintain documentation up to date /// by keeping code and documentation in the same file /// and providing a tool (/doc compiling option) to extract /// those comments and put them in a useful form (XML) /// XML file is: /// interpreted in certain ways inside of Visual Studio .NET or /// can be styled with XSLT to produce a Web page or /// printable documentation. warning CS1587: XML comment is not placed on a valid language element

Hello, World; Generating XML documentation from comments (2/2)

Produced when compiled with /doc option: >csc /doc:hello.xml hello.cs


<?xml version="1.0" ?> <doc> <assembly> <name>hello</name> </assembly> <members> <member name="T:Hi">This is a class containing the entry point of the application</member> <member name="M:Hi.Main"> The entry point is named <c>Main</c> It has no parameter </member> </members> </doc>

The XML consists of a doc element, which is for the assembly named hello

A tag introduced by user All the other tags are generate by the compiler

Documentation example (from [5]) (1/2)


<paramref/>empty tag is used when commenting a method to indicate that the value of the name attribute is actually using System; the name of one of the methods arguments. namespace ThinkingIn.CSharp.Chap03{ ///<summary>Shows doc comments</summary> <see> tags are intended for cross ///<remarks>The documentation comments within C# references to other ///are remarkably useful, both within the Visual code elements or other documentation fragments. ///Studio environment and as the basis for more ///significant printed documentation</remarks> public class HelloDate2 { One of <param> tags should be ///<summary>Entry point</summary> written for each argument ///<remarks>Prints greeting to to a method; the value of the name attribute specifies /// <paramref name="args[0]"/>, gets a which argument. The description /// <see cref="System.DateTime">DateTime</see> should include any preconditions associated with the /// and subsequently prints it</remarks> argument. ///<param name="args">Command-line should have a ///single name. All other args will be ignored ///</param> D:\Tudor\Csharp\DocumentationComments>HelloWithDate Tudor public static void Main(string[] args) { Results: Hello, Tudor it's: Console.WriteLine("Hello, {0} it's: ", 2/24/2009 11:54:50 AM args[0]); Console.WriteLine(DateTime.Now); } } }//:~

Documentation example (from [5]) (2/2)


<?xml version="1.0"?> <doc> <assembly> <name>HelloWithDate</name> </assembly> <members> <member name="T:ThinkingIn.CSharp.Chap03.HelloDate2"> <summary>Shows doc comments</summary> <remarks>The documentation comments within C# are remarkably useful, both within the Visual Studio environment and as the basis for more significant printed documentation</remarks> </member> <member name="M:ThinkingIn.CSharp.Chap03.HelloDate2.Main(System.String[])"> <summary>Entry point</summary> <remarks>Prints greeting to <paramref name="args[0]"/>, gets a <see cref="T:System.DateTime">DateTime</see> and subsequently prints it</remarks> <param name="args">Command-line should have a single name. All other args will be ignored </param> </member> </members> </doc>

Console and Windows applications (1/2)


Console application: designed to be run in a programm environment that supports a quaint and old-fashioned text-only computer interface (known as console or command line interface):
Input: from a typewriter Output: there is no positioning of text in the page (the function printf for example displays the thext wherever the teletypewriter head or the cursor of a videobased command line happens to be at the time ) In MS Windows, the command line interface exists in the form of an application window called MS_DOS Windows or Command Prompt Windows (CPW). When a console appl terminates, it leaves behind its output to the console, as long as MS-DOS Windows does exist. In C#: console input and output came through the class System.Console.

Windows application:
Class derived from System.Windows.Forms.Form creates its own window Works with graphics , Works with mouse When an Windows appl. terminates, it cleans up after itself, by distroying the windows and any output thats displayed. C#: the namespace System.Windows.Forms

Remark. There are mixed applications too.

Console and Windows applications (2/2)


C#: the difference between a console and a Windows application is made by the compiler option /target (/target:exe or /target:winexe) An application designed for console could also be compiled as a Windows appl ( /target:winexe) and a Windows appl. as a Console appl ( /target:exe) The following table summarizes the behavior:
Compiling as a Console application /t:exe Start from Command prompt

Start from Windows

Click to edit the outline text format


Start from Command prompt Start from Windows

Compiling as a Windows application /t:winexe

there is console output

Second Outline Level


no console output

Console app.
(System. Console)

Windows app
(System.Windows)

MS-DOS prompt does not return until program terminates -the results remain displayed

Windows -creates a CP W -CP W is destroyed at termination (results disapear)

debug mode: MSDOS prompt return immediately, before program terminates release mode: Press any key

Third Outline Level Fourth Outline Level


creates Form window no CPW

Errors

Hello, Console application; /target:exe


// taken from using System; ///This is a class containing the entry point of a console application public class Hi{ /// The entry point is named <EM>Main</EM> /// It has no parameter public static void Main(){ Console.WriteLine(Hello!"); Console.ReadKey(); } } Compiler option /target:exe Started from within a Command Prompt windows:

Any Console out are displayed The MS DOS prompt does not return until program terminates and the results remain displayed The Windows OS creates a Command Prompt windows Any Console out are displayed, but the Command Prompt windows disappears at termination.

Started from Windows:


Use Console.ReadKey(); to force the window to remain displayed.

Hello, Windows Forms application;/target:winexe (1/2) // from D:\Tudor\Csharp\Hello\winhello.cs


using System; using System.Windows.Forms; using System.Drawing; public class HelloWorld:Form{ [STAThread] public static void Main(){ System.Console.WriteLine("Hello from Main, Console!"); Application.Run(new HelloWorld()); System.Console.WriteLine("Hello from Main, Console!"); } public HelloWorld(){ this.Text="Hello, world"; label=new Label(); label.Text="Hello ! \u0417\u0414\u041E!"; label.Size=new Size(label.PreferredWidth, label.PreferredHeight); label.Location=new Point(50,50); this.Controls.Add(label); this.Size=new Size(400,200); } Label label; }

Hello, Windows Forms application (2/2)


Compiler option /target:winexe The Windows Form is displayed, but Console out are not displayed, it goes into the bit bucket Started from within a Command Prompt windows:

Command Prompt window behaves differently depending whether you are in:

release mode (youll see standard Press any key message) debug mode (the Console window will disapear without any warning)

Started from Windows:

The Windows OS does not create a Command Prompt windows

Explanation. Debug and Release are different configurations for building your project. As the name implies, you generally use the Debug mode for debugging your project, and the Release mode for the final build for end users. The Debug mode does not optimize the binary it produces (as optimizations can greatly complicate debugging), and generates additional data to aid debugging. The Release mode enables optimizations and generates less (or no) extra debug data.

Displying Forms
quik display closing after sleep //2 using System.Windows.Forms; using System.Threading; class ShowForm{ public static void Main(){ Form f=new Form(); f.Show(); Thread.Sleep(2000); f.Text="Sara"; Thread.Sleep(4000); } } application closes when form closes //3 using System.Windows.Forms; using System.Threading; class ShowForm{ public static void Main(){ Form f=new Form(); f.Show(); Thread.Sleep(2000); f.Text="Sara"; Application.Run(); // From System.Windows.Forms namespace } } //4 using System.Windows.Forms; using System.Threading; class ShowForm{ public static void Main(){ Form f=new Form(); f.Show(); Thread.Sleep(2000); f.Text="Sara"; Application.Run(f); } } //1 using System.Windows.Forms; class ShowForm{ public static void Main(){ Form f=new Form(); f.Show(); } }

application stil running after closing form

while (not close event from f ){ }

Compiling Source Code into Managed Modules

MSIL- Microsoft Intermediate Language (1/2)

IL is stack based, which means that all of its instructions push operands onto an execution stack and pop results off the stack. ( IL offers no instructions to manipulate registers) IL is a much higherlevel language than most CPU machine languages. You can think of IL as an object-oriented machine language. IL can access and manipulate object types has instructions to create and initialize objects, call virtual methods on objects, and manipulate array elements directly. It even has instructions to throw and catch exceptions for error handling. However, as any other machine language, IL can be written in assembly language, and Microsoft does provide an IL Assembler, ILAsm.exe. Microsoft also provides an IL Disassembler, ILDasm.exe.

MSIL- Microsoft Intermediate Language (2/2)


Assures programs portability Assures .NET compatibility: an application may use compiled components written in different .NET compatible languages; the client application uses /reference:server_file compiler option Facilitates the verification process;

part of the job of JIT compiler is to verify that the code is accessing memory properly and that it is using the correct variable types when calling methods. The MSIL instruction set was designed to make this process relatively straightforward. Note that usually the CPU- specific code is optimized for quick execution and becomes hard to understand and verify. Code Metadata= a kind of table of content of the compiled code. It contains information about the structure if the classes, the signatures of the methods etc. This information is used by clients of the compiled code and assures .NET compatibility

MSIL code consist of::


Compiling process

C# command line compiler (MS SDKs csc.exe) (1/3)


> csc /help
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.3053 for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727 Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

Visual C# 2005 Compiler Options

- OUTPUT FILES /out:<file> or first file) /target:exe /target:winexe /target:library /target:module form: /t:module) / /doc:<file> /keyfile:<file> /keycontainer:<string> /platform:<string> XML Documentation file to generate Specify a strong name key file Specify a strong name key container Limit which platforms this code can run on: x86, Itanium, x64, or Specify output file name (default: base name of file with main class Build a console executable (default) (Short form: /t:exe) Build a Windows executable (Short form: /t:winexe) Build a library (Short form: /t:library) Build a module that can be added to another assembly (Short

C# command line compiler (csc) (2/3)


- INPUT FILES /recurse:<wildcard> Include all files in the current directory and subdirectories according to the wildcard specifications /reference:<alias>=<file> Reference metadata from the specified assembly file using the given alias (Short form: /r) /reference:<file list> form: /r) /addmodule:<file list> Reference metadata from the specified assembly files (Short Link the specified modules into this assembly

- CODE GENERATION /debug[+|-] Emit debugging information /debug:{full|pdbonly} Specify debugging type ('full' is default, and enables attaching a debugger to a running program) /optimize[+|-] Enable optimizations (Short form: /o)

C# command line compiler (csc) (3/3)


- LANGUAGE /checked[+|-] /unsafe[+|-] /define:<symbol list> /langversion:<string> - MISCELLANEOUS /help @<file> - ADVANCED /codepage:<n> /utf8output Specify the codepage to use when opening source files Output compiler messages in UTF-8 encoding Display this usage message (Short form: /?) Read response file for more options Generate overflow checks Allow 'unsafe' code Define conditional compilation symbol(s) (Short form: /d) Specify language version mode: ISO-1 or Default

/main:<type> Specify the type that contains the entry point (ignore all other possible entry points) (Short form: /m) /lib:<file list> Specify additional directories to search in for references /moduleassemblyname:<string> Name of the assembly which this module will be a part of.

Response files

A response file is a text file that contains a set of compiler command-line switches. the compiler opens response files and uses any switches that are specified in them as though the switches were passed to CSC.exe on the command line.

Example. >csc.exe @MyProject.rsp CodeFile1.cs CodeFile2.cs /out:MyProject.exe /target:winexe MyProject.rsp contains:

The CLR's Execution Model

Jeffrey Richter, ch 1.

CLR managed modules


(i.e, requires CLR to execute )

(J. Richter, CLR via C#)

indicates the type of file: GUI, CUI, or DLL, contains a timestamp indicating when the file was built.

Regardless of which compiler you use,

(C#, Visual Basic, JScript, J# (a Java language compiler), IntermediateLanguage Assembler (ILAsm.exe), etc. )

PE32 or PE32+ header CLR header

the result is a managed module.


Microsoft's C++ compiler builds EXE/DLL modules that contain unmanaged code and unmanaged data (don't require the CLR to execute.). However, by specifyingthe /CLR command-line switch, the C++ compiler produces modules that contain managed code, (CLR must A managed module is a standard then be installed to 32-bit Microsoft Windows portable execute this code executable (PE32) file or a standard 64bit Windows portable executable (PE32+) file that requires the CLR to execute.

Click to edit the Metadata Tables outline text format


Definition Table

Second Outline Reference Level Table


IL code

Contains the information (interpreted by the CLR and utilities) that makes this a managed module: entry point method (Main method), the location/size of the module's metadata, resources, strong name, some flags etc.

All CLR-compliant compilers produce Intermediate Language (IL) code instead code targeted to aspecific CPU architecture CLR compiles the IL into native CPU instructions.

Third Outline Level Fourth Outline Level

See next slide for details!

Use of Metadata Tables (J. Richter, CLR via C#)


Metadata removes the need for header and library files when compiling because all the information about the referenced types/members is contained in the file that has the IL that implements the type/members. Compilers can read metadata directly from managed modules. Microsoft Visual Studio uses metadata to help you write code. Its IntelliSense feature parses metadata to tell you what methods, properties, events, and fields a type offers, and in the case of a method, what parameters the method expects. The CLR's code verification process uses metadata to ensure that your code performs only "safe" operations. Metadata allows an object's fields to be serialized into a memory block, sent to another machine, and then deserialized, re-creating the object's state on the remote machine. Metadata allows the garbage collector to track the lifetime of objects. For any object, the garbage collector can determine the type of the object and, from the metadata, know which fields within that object refer to other objects.

Combining Managed Modules into Assemblies


The CLR doesn't actually work with modules, it works with assemblies. an assembly is : a logical grouping of one or more modules or resource files. is the smallest unit of reuse, security, and versioning. Depending on the choices you make with your compilers or tools, you can produce a single-file or a multifile assembly. In the CLR world, an assembly is what we would call a component

Click to edit the outline text format

a single PE32(+) file that Second Outline represents the logical grouping of files. Level contains a block of data called

the manifest. The manifest is simply another set of metadata tables. These tables describe the files that make up the assembly the publicly exported types implemented by the files in the assembly the resource or data files that are associated with the assembly.

Third Outline Level Fourth Outline Level

Combining modules

Combining by compiling

>csc /t:module TR.cs >csc /out:JeffTypes.dll /t:library /addmodule:TR.netmodule TF.cs

Combining by linking

Assembly Linker (MS SDKs al.exe) >al


Microsoft (R) Assembly Linker version 9.0.30729.1 Copyright (C) Microsoft Corporation. All rights reserved.

Usage: al [options] [sources] Sources: (at least one source input is required) <filename>[,<targetfile>] add file to assembly etc.

Options: ('/out' must be specified) /? or /help Display this usage message /main:<method> Specifies the method name of the entry point /out:<filename> Output file name for the assembly manifest /t[arget]:lib[rary] Create a library etc.

>csc /t:module TR.cs >csc /t:module TF.cs >al /out:JeffTypes.dll /t:library TF.netmodule TR. netmodule.

Executing Assembly's Code

Loading the Common Language Runtime (CLR)

Each assembly is either an executable application or a DLL containing a set of types for use by an executable application. CLR is responsible for managing the execution of code contained within these assemblies. This means that the .NET Framework must be installed on the host machine. Microsoft has created a redistribution package that you can freely ship to install the .NET Framework on your customers' machines. Some versions of Windows ship with the .NET Framework already installed. The existence of MSCorEE.dll file in the %SystemRoot%\system32 tells you that the .NET Framework is installed. When running an executable file, Windows :

examines this EXE file's header and creates a process for the application. loads the suitable version of MSCorEE.dll into the process's address space. primary thread calls a method defined inside MSCorEE.dll. This method initializes the CLR, loads the EXE assembly, and then calls its entry point method (Main).

Just In Time (JIT) compiling

CLRs Just In Time compiler translate MSIL to a specific CPU


At the time the bytecode MSIL is run, the just-in-time compiler will compile some or all of it to native machine code for better performance. This can be done per-file, per-function or even on any arbitrary code fragment; the code can be compiled when it is about to be executed (hence the name "just-in-time"). JIT typically causes a slight delay in initial execution of a method, due to the time taken to compile the bytecode. Sometimes this delay is called "startup time delay". The JIT compiler stores the native CPU instructions in dynamic memory. This means that the compiled code is discarded when the application terminates.

So if you run the application again in the future or if you run two instances of the application simultaneously (in two different operating system processes), the JIT compiler will have to compile the IL to native instructionsagain .

most implementations of Java, rely on JIT compilation for high-speed code execution. In Sun's HotSpot JVM, the application code is initially interpreted, but the JVM monitors which sequences of bytecode are frequently executed and translates them to machine code for direct execution on the hardware

JIT: calling a method for the first time

(J. Richter, CLR via C#)

JIT: calling a method for the first time

(J. Richter, CLR via C#)

in dynamic memory. compiled code is discarded when the application terminates.

Application Deployment

Privately deployed assemblies


Assemblies deployed in the application's base directory or one of its subdirectories A weakly named assembly can be deployed only privately. Simple install/move/uninstall scenario (because each assembly has metadata indicating which referenced assembly should be loaded; no registry settings are required)

Globally deployed assembly

Globally deployed: an assembly that is deployed into some well-known location that the CLR looks in when it's searching for the assembly. No relation between application directory and shared assembly directory A strongly named assembly can be deployed privately or globally. A weakly named assembly can be deployed only privately

Privately deployed assemblies


If assembly damaged (use an editor to modify stringer. Dll ), CLR error Unhandled Exception: System.BadImageFormatE xception: Could not load file or assembly

csc /t:module stringer.cs al /t:library /out:stringer.dll stringer.netmodule both stringer.dll and stringer.netmodule must be in appl dir. ildasm stringer.dll csc /t:exe /r:stringer.dll client.cs If assembly missing (not in the same directory) Unhandled Exception: System.IO.FileNotFoundException : Could not load file or assembly

We can replace stringer.dll by another version. No need to recompile client, application still works

(simple) Assemblies Administrative Control (Configuration) Here, an application can control its directory and its subdirectories but has no contr
.

To allow administrative control over an application, a configuration file can be placed in the application's directory.
Whenever the CLR attempts to locate an assembly file, it always looks in the application's directory first, and then in the AuxFiles subdirectory

Appdir\client.exe.config

<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="AuxFiles" /> </assemblyBinding> </runtime> You can specify multiple </configuration>

semicolon-delimited paths can't specify an absolute path

D:\Tudor\Csharp\Assembly\StronglyNamed client.exe client.exe.config D:\Tudor\Csharp\Assembly\StronglyNamed \AuxFiles stringer.dll +stringer.netmodule

Directory structure Shared assembly must be in a subdirectory

Probing for Assembly Files

(J. Richter, CLR via C#)

When the CLR needs to locate an assembly, it scans several subdirectories. Here is the order in which directories are probed for a culture-neutral assembly (where firstPrivatePath and secondPrivatePath are specified via the config file's privatePath attribute):

AppDir\AsmName.dll AppDir\AsmName\AsmName.dll AppDir\firstPrivatePath\AsmName.dll AppDir\firstPrivatePath\AsmName\AsmName.dll AppDir\secondPrivatePath\AsmName.dll AppDir\secondPrivatePath\AsmName\AsmName.dll

In this example, no configuration file would be needed if the stringer.dll assembly files were deployed to a subdirectory called

D:\Tudor\Csharp\Assembly\StronglyNamed\STRINGER
since the CLR would automatically scan for a subdirectory whose name matches the name of the assembly being searched for.

Strongly named assemblies

Windows DLL hell!


Replacing a *.dll with a new version, the applications uses this new version (instability, sometimes!) .NET Framework addresses the DLL hell by Strongly named assemblies

differentiating assemblies simply by using a file name isn't good enough. The CLR supports some mechanism that allows assemblies to be uniquely identified: strongly named assembly: a file name (without an extension), a version number, a culture identity, and a public key.(in fact, a public key token.) The following assembly identity strings (sometimes called an assembly display name) identify four completely different assembly files:

"MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture="en-US", PublicKeyToken=b77a5c561934e089" "MyTypes, Version=2.0.1234.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

The combination of the file name, the assembly version, the culture, and the public key gives this assembly a strong name, which is guaranteed to be unique.

Strongly named assemblies


It is highly recommended that you strongly name all of your assemblies. differentiating assemblies simply by using a file name isn't good enough A strongly named assembly consists of four attributes that uniquely identify the assembly:

a file name (without an extension), a version number, a culture identity, a public key (in fact, a hash value called a public key token).

Example: four completely different assembly files:


"MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture="en-US", PublicKeyToken=b77a5c561934e089" "MyTypes, Version=2.0.1234.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

Strongly Named Assembly


>sn k stringer.keys

(J. Richter, CLR via C#)

1: Key pair (public, private) written to Public key written to There is no way to display the private key

>sn p stringer.keys stringer.public

>sn tp stringer.public

Public key displayed: 0024too long to work with! Public key token (8 bytes) were created to work instead: 0e81d4e3e46e6503 2: create a strongly named assembly (you can see it :>ILDasm stringer.dll) 3: create an assembly referencing a strongly named assembly Unhandled Exception: System.IO.FileLoadExceptio n: PublicKeyToken= 0e81d4e3e46e6503 (The new one has abea2e3102479fb3)

>csc /t:library /keyfile:stringer.keys stringer.cs >csc /t:exe r:/stringer.dll client.cs >client

Repeating 1; and 2; to create an updated version of stringer.dll, >client (and no compilation of client) Does not work

Repeating only 2: works!

Signing an assembly

The Global Assembly Cache (1/2)

If an assembly is to be accessed by multiple applications, the assembly must be placed into a well-known directory, and the CLR must know to look in this directory automatically when a reference to the assembly is detected. This well-known location is called the global assembly cache (GAC), C:\Windows\Assembly: The GAC directory is structured: It contains many subdirectories, and an algorithm is used to generate the names of these subdirectories. You should never manually copy assembly files into the GAC The most common tool for installing a strongly named assembly into the GAC is GACUtil.exe.

The Global Assembly Cache (2/2)

When you install the .NET Framework, a Windows Explorer shell extension (ShFusion.dll) is installed. This shell extension also knows the structure of the GAC, and it displays the GAC's contents in a nice, user-friendly fashion. GAC directory tree may be shown from command prompt (>dir)
version
10.0.0.0 .

assembly name
Microsoft.SqlServ er.XmlSrc

culture
Neutral .

public key token


89845dcd8080cc 91

Processor architecture
MSIL

you can drag a strongly named assembly file containing a manifest to an Explorer window. When you do this, the shell extension installs the assembly's files into the GAC.

Instaling/uninstaling in GAC
>gacutil /? >gacutil /i stringer.dll

Look in windows/assembly to see your installed assembly

move client.exe anywere CLR succed to find stringer.dll

>client

>gacutil /u stringer >client Instead of gacutil, you can use drag and drop to install! System.IO.FileNot FoundException:

Look again in windows/assembly no stringer.dll now!

(Advanced) Assemblies Administrative Control (Configuration) (1/2)

In addition to deploying a strongly named assembly in the GAC or privately, a strongly named assembly can be deployed to some arbitrary directory that a small set of applications know about. For example, you might be producing 3 applications, all of which want to share a strongly named assembly. Upon installation, you can create 4 directories:
one for each application and an additional directory for the assembly you want shared.

When you install each application into its directory,


also install an XML configuration file, and have the shared assembly's codeBase element indicate the path of the shared assembly.

Advanced Administrative Control (Configuration) (2/2) Appdirectory


Appdirectory\client.exe.config
client.exe client.exe.config
D:\Tudor\Csharp\Assembly\StronglyNamed

<?xml version="1.0" ?> stringer.dll <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- one dependentAssembly per unique assembly name --> Directory structure <dependentAssembly> No relation between <assemblyIdentity application directory and name="stringer" shared assembly publicKeyToken="87eb9818eb22c63e" /> directory <!-- one codeBase per version --> <codeBase version="0.0.0.0" href="file://D:/Tudor/Csharp/Assembly/StronglyNamed/Shared/stringer.dll"/> </dependentAssembly> Indicate the path of the shared </assemblyBinding> assembly </runtime> </configuration>

\Shared

Delayed (Partial) Signing

Control of Names

Scope

Scope of a name: the region of program text in which the name can be refered to without qualification
4 scopes:
1.

public class Bank{ public class Account{ public void Deposit(decimal amount){ balance += amount; } private decimal balance; } public Account OpenAccount( ) { ... } }

Global scope, Bank class scope, Account class scope, body of the Account.Deposit method

2.

3.

4.

When a name is not in scope, you cannot use it without qualification. This happens when:

The scope is ended

The name is hidden

class Top{ public void M( ) { ... } } class Bottom: Top{ new public void M( ){ M( ); // Recursion base.M( ); // Needs qualification to avoid recursion } }

public struct Point{ public Point(int x, int z){ this.x = x; // Needs qualification y=z; } private int x, y; }

Control of names (C, C++)


control of names: when use the same name in more modules of the program, prevent the names from clashing name clashes: two different entities having the same name, in the same scope C, often an unmanageable sea of names. C++: namespace Vendor1 { class String { ... }; } namespace Vendor2 { class String { ... }; } // how those names can be accessed via qualification: Vendor2::String s; using directive: using namespace Vendor2; // makes String available for use, but doesn't declare it String s; using declaration: using Vendor2::String; String s; //actually introduces Vendor2::String into the current scope as a declaration //using Vendor1::String; //using Vendor2::String; //will trigger a "duplicate declaration" compiler error.

Namespaces (1/2)
Namespaces: Resolving Name Clashes

in C#, use namespaces to resolve. C# namespaces are similar to C++ namespaces and Java packages. Internal access is not dependent on namespaces. Multiple levels of organisation by nesting namespaces A namespace, unlike a class, is an open scope (it is allowed to subsequently reopen it, even in a different source file). Consequences: Multiple source files:Collaborating classes that are located in a common namespace can still be implemented across several physical source files (typically one source file per class) rather than in one large source file. Extensible namespaces: A new class can be added to a namespace without affecting any of the classes already inside the namespace. In contrast, adding a new method to an existing class requires the whole class to be recompiled. Access Levels:

Namespaces are implicitly public. No access modifiers is allowed when you declare a namespace Elements defined in a namespace cant be declared private, protected or protected internal. They are implicitely declared internal (accessible in the same namespace). Can be declared as public.

Namespaces allow classes to be logically grouped together inside a named space.

Namespaces (2/2)
A1 A2

M1

M2

There is no implicit relationship between a namespace and a project or assembly. An assembly can contain classes from different namespaces classes from the same namespace can be located in different assemblies. The name of the enclosing space becomes part of the full name of the class (fully qualified names) Directive using: use classes outside their namespaces without using their fully qualified names.

brings all the types inside the namespace into scope

Declaring using-namespace-directives at Global Scope: before any member declarations when they are used in global scope Declaring using-directives Inside a Namespace: before any member declarations. The effect is strictly limited to the namespace body in which it appears. using-namespace-directives Are Not Recursive: gives unqualified access to the types contained in namespace, but not to the namespaces nested using Alias Directives for a Deeply Nested Namespace or Type Mixed using-directives never affect each other; they only affect the member declarations that follow them

Namespaces: examples (1/2)


namespace A{ namespace L1{ public class C{} } } namespace B.L1{ public class C{} } namespace A.L2{ public class C{} } namespace B.L2{ public class C{} } namespace N{ using A.L1; class C{ C c;} } namespace M{ using A; class C{ L1.C c;} }

File namespaces.cs, compile with >csc /target:module namespaces.cs Compiling result: namespaces.netmodule

a shorthand

Using directive are not recursive: Errror: type or namespace L1 could not be found

Namespaces: examples (2/2)


Compile with
using B.L1; using a1=A.L1; using A.L2; using A; using aClass=A.L2.C; class S{ A.L1.C a1; A.L2.C a2; a1.C y1;// A.L1.C aClass x; // A.L2.C //C b; //L1.C w; }

>csc /t:module /addmodule:namespaces.netmodule using directive: can be


applied only for namespaces for a namespace

alias using directive for a namespace alias using directive for a type
Error: an ambiguous reference to B.L1.C and A.L2.C

Error: type or namespace "L1" could not be found

Imaginary numbers: two representations (1/2)


namespace RectangularRepresentation { struct Complex{ private double real; public double Real{ get { return real; } set { real = value; } } private double i; public double I { get { return i; } set { i = value; } } } } namespace PolarRepresentation { struct Complex{ private double radius; public double Radius{ get { return radius; } set { radius = value; } } private double angle; public double Angle { get { return angle; } set { angle = value; } } } }

Imaginary numbers: two representations (2/2)

namespace Application { using RectangularRepresentation; class Program { static void Main(string[] args) { Complex z = new Complex();//RectangularRepresentation z.I = 1; z.Real = 1; PolarRepresentation.Complex p = new PolarRepresentation.Complex(); p.Angle = System.Math.PI / 4; p.Radius = System.Math.Sqrt(2); } } }

Access modifiers

Access modifiers define the level of access that certain code has to class members such as methods and properties. You need to apply the desired access modifier to each member, otherwise the default access type is implied. public A public member is accessible from anywhere. This is the least restrictive access modifier. The scope of a public: the whole assembly. No two public with the same name in an assembly. protected A protected member is accessible from within the class and all derived classes. No access from the outside is permitted. private A private member is accessible only from within the same class. Not even derived classes can access it. internal An internal member is accessible from within any part of the same .NET assembly. You can think of it as public at the assembly level and private from outside the assembly. The scope of an internal: the whole namespace. No two internal with the same name in a namespace. protected internal /internal protected(means protected or internal) An internal protected member is accessible from within the current assembly or from within types derived from the containing class.

internal: different namespaces, the same assembly


csc /t:module NS1mod1.cs

//file NS1mod1.cs namespace NS1{ public class P{ internal static int i=0; private static int x=0; } class R{ //internal by default int i=P.i //int x=P.x;error: NS1.P.x inaccessible //due to its protection level } }

The internal NS1.P.i accessible in NS2, due to the fact that the two different namespaces are in the same assembly

csc /t:module /addmodule:NS1mod1.netmodule NS2.cs

//file NS2.cs namespace N2{ internal class J{ void m(){ NS1.P.i=1; //accessible, in the same assembly NS1.R r; //accessible, in the same assembly //NS1.P.x=1; error: NS1.P does not containes a definition for x } } }

A namespace spread out over different modules


//file NS1mod2.cs namespace NS1{ class C{ int x=NS1.P.i; } }

If compiled with: >csc /t:module NS1mod2.cs the namespace or type P does not exists in the namespace N1 are you missing an assembly refference?

Compile with: >csc /t:module /addmodule:NS1mod1.netmodule NS1mod2.cs to give access to another module

Framewark Class Library (1/2)


(J. Richter, CLR via C#)

The .NET Framework includes the Framework Class Library (FCL). The FCL is a set of DLL assemblies that contain several thousand type definitions in which each type exposes some functionality. Some kinds of applications developers can create by using these assemblies:

Web services Methods that can process XML-based messages sent over the Internet very easily. Web Forms HTML-based applications (Web sites). Typically, Web Forms applications will make database queries and Web service calls, combine and filter the returned information, and then present that information in a browser by using a rich HTML-based user interface. Windows Forms Rich Windows GUI applications. Instead of using a Web Forms page to create your application's UI, you can use the more powerful, higher-performance functionality offered by the Windows desktop. Windows Forms applications can take advantage of controls, menus, and mouse and keyboard events, and they can exchange information directly with the underlying operating system. As can Web orms applications, Windows Forms applications can also make database queries and consume Web ervices. Windows console applications Windows services Yes, it is possible to build service applications that are controllable via the Windows Service Control Manager (SCM) by using the .NET Framework. Component library The .NET Framework allows you to build stand-alone assemblies (components) containing types that can be easily incorporated into any of the previously mentioned application types.

Framewark Class Library (2/2)


(J. Richter, CLR via C#)

Because the FCL contains literally thousands of types, a set of related types is presented to the developer within a single namespace. To access any of the framework's features, you need to know which namespace contains the types that expose the facilities you're after.

developers can easily create their own namespaces containing their own types.

Click to edit the outline text format

Second Outline Level

Third Outline Level Fourth Outline Level

Common Type System (1/4)


(J. Richter, CLR via C#) pg 22

Because types are at the root of the CLR, Microsoft created a formal specification-the Common Type System (CTS)-that describes how types are defined and how they behave. CLR's CTS defines the behavior of the type.

the syntax you use for defining the type is different depending on the language you choose, but the behavior of the type will be absolutely identical regardless of the language

The CTS specification states that a type can contain zero or more members. Field A data variable that is part of the object's state. Method Methods have a name, a signature, and modifiers. Property Properties allow an implementer to validate input parameters They also allow a user of the type to have simplified syntax. Finally, properties allow you to create read-only or write-only "fields." To the caller, this member looks like a field. But to the type implementer, it looks like a method (or two). Event An event allows a notification mechanism between an object and other interested objects. For example, a button could offer an event that notifies other objects when the button is clicked.

Common Type System (2/4)

1. 2. 3.

(J. Richter, CLR via C#) pg 22

CTS also specifies the rules for


type visibility and access to the members of a type. In addition, the CTS defines the rules governing type inheritance, virtual methods, object lifetime, and so on. public (called public) exports the type, making it visible and accessible to any assembly. assembly (called internal in C#) makes the type visible and accessible to code within the same assembly only.

1.

Type visibility:

Common Type System (3/4): access to the members of a type

(J. Richter, CLR via C#) pg 22

A type that is visible to a caller can further restrict the ability of the caller to access the type's members. Valid options for controlling access to a member: Private The method is callable only by other methods in the same class type. Family The method is callable by derived types, regardless of whether they are within the same assembly. Note that many languages (such as C++ and C#) refer to family as protected. Family AND assembly The method is callable by derived types, but only if the derived type is defined in the same assembly. Many languages (such as C# and Visual Basic) don't offer this access control. Of course, IL Assembly language makes it available. Assembly The method is callable by any code in the same assembly. Many languages refer to assembly as internal. Family OR assembly The method is callable by derived types in any assembly. The method is also callable by any types in the same assembly. C# refers to family or assembly as protected internal. Public The method is callable by any code in any assembly.

Common Type System (4/4): predefined System.Object


Here's another CTS rule. All types must (ultimately) inherit from a predefined type: System.Object. This Object is the root of all other types and therefore guarantees that every type instance has a minimum set of behaviors. Specifically, the System.Object type allows you to do the following:

Compare two instances for equality. (public virtual bool object.Equals(object obj)) Obtain a hash code for the instance. (public virtual int object.GetHashCode()) Query the true type of an instance. (public System.Type object.GetType()); it is not virtual Perform a shallow (bitwise) copy of the instance. Obtain a string representation of the instance's object's current state. (string object.ToString())

Example: System.Object (1/3)


// file using System; // The Point class is derived from System.Object. class Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public override bool Equals(object obj) { // If this and obj do not refer to the same type, then they are not equal. if (obj.GetType() != this.GetType()) return false; // Return true if x and y fields match. Point other = (Point)obj; return (this.x == other.x) && (this.y == other.y);

Example: System.Object (2/3)


// Return the XOR of the x and y fields. public override int GetHashCode() { return x ^ y; } // Return the point's value as a string. public override String ToString() { return String.Format("({0}, {1})", x, y); } // Return a copy of this point object by making a simple field copy. public Point Copy() { return (Point)this.MemberwiseClone(); } }

Example: System.Object (3/3)


public sealed class App the following output: // { // False static void Main() // True // True { // p1's value is: (1, 2) // Construct a Point object. Point p1 = new Point(1, 2); // Make another Point object that is a copy of the first. Point p2 = p1.Copy(); // Make another variable that references the first Point object. Point p3 = p1; // The line below displays false because p1 and p2 refer to two different objects. Console.WriteLine(Object.ReferenceEquals(p1, p2)); // The line below displays true because p1 and p2 refer to two different objects that have the same value. Console.WriteLine(Object.Equals(p1, p2)); // The line below displays true because p1 and p3 refer to one object. Console.WriteLine(Object.ReferenceEquals(p1, p3)); // The line below displays: p1's value is: (1, 2) Console.WriteLine("p1's value is: {0}", p1.ToString()); } }
// This code example produces

Overriding Equals

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Equals { class C { int x = 0; } class CO { C c; int x = 0; public CO(C y) { c = y; } public override bool Equals(object obj) { if (obj == null) return false; if (this.GetType() != obj.GetType()) return false; // now, the same type CO co = (CO)obj; // no exception // compare reference types if (!Object.Equals(c,co.c)) return false;

Overriding Equals

public static Boolean operator==(CO x, CO y) { //warning, wheather not //if (x == null) return false; error StackOverflowException Why? (recursive ==) //if (null == x) return false; if (ReferenceEquals(x, null)) return false; return x.Equals(y); } public static Boolean operator !=(CO x, CO y) { //required by == return !(x==y); } public override int GetHashCode() { return x % 10; } }

Overriding Equals

class Program {

static void Main(string[] args) { Console.WriteLine("Hello to Equals"); Console.WriteLine(" virtual bool object.Equals(object o)"); C a = new C(); C b = new C(); Console.WriteLine(a==b); //False Console.WriteLine(a.Equals(b)); //False Console.WriteLine(a == null); //False Console.WriteLine(a.Equals(null)); //False

Console.WriteLine(" virtual bool CO.Equals(object o) and operator=="); CO c = new CO(a); CO d = new CO(b); Console.WriteLine(c.Equals(d)); //False Console.WriteLine(c.Equals(a)); //False, no exception Console.WriteLine(c.Equals(null)); //False, no exception d = new CO(a); Console.WriteLine(c.Equals(d)); //True Console.WriteLine(c==d); //True;

Common Language Specification


(J.

Richter, CLR via C#) pg 22

Types of .NET applications


End- user application (a command prompt or Windows executable .exe file); use the compiler options: /target:exe /target:winexe Code library to be a server for other classes a module, *.netmodule, /target:module an assembly as logical DLL, *.dll; /target:library Response files

A response file is a text file that contains a set of compiler command-line switches. The compiler opens response files and uses any switches that are specified in them. >csc.exe @MyProject.rsp CodeFile1.cs CodeFile2.cs

Modules (see C# MSDN Training)

Source files: compiled into:


Portable executable (PE) files Example: c:\> csc /out:app.exe /target:exe bank.cs app.cs .NET dynamic -link library (DLL) modules

Example:

c:\> csc /out:bank.mod /target:module bank.cs bankaccount.cs (creates module bank.mod) c:\> csc /target:module bank.cs bankaccount.cs (creates module bank.dll)

DLL modules must be self-contained Extension .mod instead .dll: prevent from accidentally trying to execute a module

DLL modules can be combined into .NET assemblies (toplevel units of deployment)

their constituent modules are the units of download within an assembly.

Executables can only use modules that have been added to an assembly.

Assemblies

Assembly: a reusable, versionable, secure, and self -describing deployment unit for types and resources; it is the primary building block of a .NET application. An assembly consists of two logical pieces: types and resources that form some logical unit of functionality metadata that describes how these elements relate and what they depend on to work properly (called a manifest):

Identity (name, version) Contents: names of all of the types and resources that are visible outside the assembly, and information about where they can be found in the assembly. Dependencies. explicitly describes other assemblies that it is dependent upon .

Creating an assembly: from one or more source files or module files >csc /out:bank.dll /t:library /addmodule: at.mod;ba.mod;bt.mod bank.cs from DLL modules using assembly linker utility >al /out:bank.dll /t:library bank.mod other.mod Create an executable that references an assembly >csc /out:app.exe /t:exe /reference:bank.dll app.cs can only reference assemblies, not modules. Inspecting an assembly by using the Intermediate Language Disassembler (ILDASM) tool c:/> ildasm bank.dllpublic An assembly of 4 classes
internal

(phisical access control at assembly level)

class

private

Internal level access and assemblies


//file N.cs namespace N1{ using N2; public class A{ public void m(){ b.p();} private B b=new B(); } } namespace N2{ using N1; public class B{ internal void p(){ a.m();} private A a=new A(); } }
Compile with: >csc /t:module N.cs >al /t:library /out:N.dll n.netmodule -internal p() from class B accessible in class A because A and B are in the same assembly (N.dll)

Compile with: >csc /reference:N.dll useN.cs -internal b.p() is not accessible: class B and MainC are not in the same assembly

//file useN.cs using N1; using N2; public class MainC{ public static void Main(){ A a=new A(); a.m(); B b=new B(); b.p(); } }

Type visibility. Friend assemblies

When defining a type at file scope (versus defining a type nested within another type), you can specify the type's visibility as being either

public or internal (type is visible to all code within the defining assembly, and the type is not visible to code written in other assemblies)

Friend assemblies
an assembly define their types as internal while still allowing to a friend to access the types.
// For InternalsVisibleTo attribute
// This assembly's internal types can be accessed by any code written in the useafriend assembly

using System; using System.Runtime.CompilerServices; [assembly:InternalsVisibleTo("useafriend")] internal sealed class SomeInternalType { } using System; internal sealed class Foo { private static Object SomeMethod() { SomeInternalType sit = new SomeInternalType(); return sit; } }

// This assembly accesses the other friend assembly's internal type as if it were a public type

Multifile Assembly Example (1/2)

see http://msdn.microsoft.com/en-us/library/aa720306(VS.71).aspx

Step 1 Compiling Files with Namespaces Referenced by Other Files // Assembly building example in the .NET Framework SDK.

//compile with // csc /t:module Stringer.cs using System; namespace myStringer { public class Stringer { public void StringerMethod() { System.Console.WriteLine("This is a line from StringerMethod."); } } }

Multifile Assembly Example (2/2)

Step 2 Compiling Modules with References to Other Modules

//compile with // csc /addmodule:Stringer.netmodule /t:module Client.cs using System; using myStringer; //The namespace created in Stringer.netmodule. class MainClientApp { // Static method Main is the entry point method. public static void Main() { Stringer myStringInstance = new Stringer(); Console.WriteLine("Client code executes"); //myStringComp.Stringer(); myStringInstance.StringerMethod(); } }

Step 3 Creating a Multifile Assembly Using the Assembly Linker >al Client.netmodule Stringer.netmodule /main:MainClientApp.Main /out:myAssembly.exe
/target:exe

Example: Modules and assemblies for processing Step 2: module for a public class Complex based on a imaginary numbers Step 1: module for rectangular rectangular representation
representation as a struct
// compile with //>csc /out:rectang.netmodule /t:module rectang.cs namespace RectangularRepresentation { internal struct Complex{ private double r; internal double Real{ get { return r; } set { r = value; } } private double i; internal double I { get { return i; } set { i = value; } } } } // compile with //>csc /out:complexrectang.netmodule /t:module /addmodule:rectang.netmodule complexrectang.cs namespace Complex { public class Complex{ private RectangularRepresentation.Complex z; public Complex(double x, double y){z.Real=x; z.I=y;} public Complex add(Complex x){return new Complex(z.Real+x.z.Real, z.I+x.z.I);} } }

Step 3:making an .dll assembly from the previous two modules >al /out:complexrectang.dll /t:library complesrectang.netmodule rectang.netmodule

Step 4: an application referencing complexrectang.dll >csc /out:AppComplexRectang.exe /reference:complexrectang.dll /t:exe AppComplexRectang.cs


public class App{ public static void Main(string[] args){ Complex.Complex z1=new Complex.Complex(1,2); Complex.Complex z2=new Complex.Complex(3,4); Complex.Complex z= z1.add(z2); } }

The same class might work with a polar representation complexpolar.dll

Multiple definitions in an assembly


namespace NS1{ public class C{} class I{} }
NS1mod3.cs NS1mod2.cs

namespace NS1{ public class C{} class I{} }

Compile with: >csc /t:module NS1mod2.cs >csc /t:module NS1mod3.cs Link with:

Error: Public type NS1.C is defined in multiple places in this assembly

>al /out:x.dll /t:library NS1mod2.netmodule, NS1mod2.netmodule Compile with: >csc /t:module NS1mod2.cs >csc /t:module /addmodule:NS1mod2 NS1mod3.cs Error: namespace NS1 already contains a definition for C and I

CLR Hosting, AppDomains, Reflection

CLR hosting

(Richter, part V)

CLR Hosting

Hosting allows any (Windows) application to utilize the features of the common language runtime (CLR). this allows existing (unmanaged) applications to at least be partially written using managed code. means that third-party code (from a hosted DLL) will be running inside your process . the hosted DLL could easily have code in it that could compromise the application's data structures and code. the hosted DLL could also try to use the security context of the application to gain access to resources it should not have access to. CLR's AppDomain feature solves all of these problems. AppDomains allow third-party untrusted code to run in an existing process, and the CLR guarantees that the data structures, code, and security context will not be exploited or compromised

CLR, MSCorEE.dll revisited

Microsoft implements CLR as a COM server contained inside MSCorWks.dll When you install the .NET Framework, the COM server representing the CLR is registered in the Windows registry just as any other COM server Any Windows application can host the CLR. However, you shouldn't create an instance of the CLR COM server by calling CoCreateInstance; instead, your unmanaged host should call the CorBindToRuntimeEx function or another similar function, all of which are declared in MSCorEE.h. A single machine may have multiple versions of the CLR installed, but usualy there will be only one version of the MSCorEE.dll file (the shim) The version of MSCorEE.dll installed on the machine is the version that shipped with the latest version of the CLR installed on the machine. Therefore, this version of MSCorEE.dll knows how to find any previous versions of the CLR that may be installed.

CLR hosting: example (1/3)


an unmanaged C++ host loads the CLR and executes some code in it the unmanaged ICLRRuntimeHost Interface (MSCorEE.h C++ header)

The CorBindToRuntimeEx function is implemented in the MSCorEE.dll (the shim) (C:\Windows\System32).

CLR hosting: example (2/3)

CLR hosting: example (3/3)

Application Domains

AppDomain

AppDomain provides isolation: it is a logical container for a set of assemblies when the CLR is initialized it creates a default AppDomain; it is destroyed destroyed only when the Windows process terminates. Specific features offered by an AppDomain:

Isolation and communication : Objects created by code in one AppDomain cannot be accessed directly by code in another AppDomain Code in other AppDomains can access another AppDomain's object only by using marshalby-reference or marshal-by-value semantics. AppDomains can be unloaded (not a single assembly) AppDomains can be individually secured (determines the maximum rights granted to assemblies) AppDomains can be individually configured (affect how the CLR loads assemblies into the AppDomain. There are configuration settings related to search paths, version binding redirects, shadow copying, and loader optimizations.)

Example: A single Windows process hosting the CLR and two AppDomains
Not sharing!

not shared JITcompiled native code

not shared JITcompiled native code

shared by all AppDomains in the process

Processes, AppDomains, Threads

In Windows, a thread is always created in the context of one process, and the thread lives its entire lifetime in that process. Since multiple AppDomains can be in a single Windows process, a thread can execute code in one AppDomain and then execute code in another AppDomain. A thread can ask the CLR what AppDomain it is currently executing in (System.Threading.Thread's static GetDomain method or System.AppDomain's static CurrentDomain property) Process AppDomain threads Windows

Accessing Objects Across AppDomain Boundaries

When an AppDomain is created (System.AppDomain's static CreateDomain method), it can be assigned a friendly name. (a String that you can use to identify an AppDomain) Code in one AppDomain can communicate with types and objects contained in another AppDomain by marshaling:

marshaling by reference

public class MarshalByRefType : System.MarshalByRefObject {}

marshaling by value

[Serializable] public class MarshalByValType : System.Object {}

There are non marshalable types. // ---not [Serializable]---public class MarshalByValType : System.Object {}

Creating AppDomains, loading assemblies, creating instances

CreateDomain (however, no thread in New AppDomain)

New AppDomain Default AppDomain that contains the 'Main' method CreateInstanceAndUnwrap -causes the calling thread to transition from the current AppDomain into the new AppDomain. SomeMethod

-loads the specified assembly into the new AppDomain -searches for type and creates an instance -the thread transitions back to the default AppDomain

Marshal-by-Reference Cross-AppDomain Communication

CLR cannot allow a variable (root) living in one AppDomain to reference an object created in another AppDomain When a source AppDomain wants to send or return the reference of an object to a destination AppDomain, the CLR defines a proxy type in the destination AppDomain's loader heap

MarshalByRefType mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType");

Destination AppDomain mbrt Proxy object

Source AppDomain (ad2) Real object

SomeMethod()
mbrt.SomeMethod(

Marshal-by-Value Cross-AppDomain Communication


MarshalByValType mbvt = (MarshalByValType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByValType"); -Serialize into a byte array, -Copy array to destination -Deserialize into fields

Real and Copy: separate lifetimes, and their states can change independently of each other

Destination AppDomain mbvt Copy of the Real object SomeMethod()

Source AppDomain (ad2) Real object

A Fault Tolerant system

see C:\TUDOR\Csharp\AppDomain\FaultTolerance

In one AppDomain an exception is trown, but the threads from other AppDomains continue

See MarshallRef.cs >csc /doc:MarshallRef.xml /target:library MarshallRef.cs See FaultTolerance.cs >csc /doc:FaultTolerance.xml /reference:MarshallRef.dll faulttolerance.cs >FaultTolerance See output.txt

AppDopmain, unsafe code

The CLR does, in fact, offer the ability to execute multiple managed applications in a single OS process.
Each managed application is called an AppDomain. By default, every managed EXE file will run in its own separate address space that has just the one AppDomain.

However, a process hosting the CLR (such as Internet Information Services [IIS] or Microsoft SQL Server 2005) can decide to run AppDomains in a single OS process. By default, Microsoft's C# compiler produces safe code. Safe code is code that is verifiably safe.
However, Microsoft's C# compiler allows developers to write unsafe code. Unsafe code is allowed to work directly with memory addresses and can manipulate bytes at these addresses. This is a very powerful feature and is typically useful when interoperating with unmanaged code or when you want to improve the performance of a time-critical algorithm.

How Hosts Use AppDomains

Console and Windows Forms Applications


>appl.exe

Windows create process Create an AppDomain, load assembly The header information indicates the version of the CLR that was used to build and test the application. The shim uses this information to determine which version of the CLR to load into the process. After the CLR loads and initializes, it again examines the assembly's CLR header to determine which method is the application's entry point (Main). On exit, unload AppDomain and terminate process

Microsoft ASP.NET Web Forms and XML Web Services Applications


Web Server Web appl 1= AppDomain1 Objects and Thread for client 1 Objects and Thread for client 2 Web appl 2= AppDomain2 Objects and Thread for client 1 Objects and Thread for client 2

A fantastic feature of ASP.NET is that the code for a Web site can be changed on the fly without shutting down the Web server. When a Web site's file is changed on the hard disk, ASP.NET detects this, unloads the AppDomain that contains the old version of the files (when the last currently running request finishes), and then creates a new AppDomain, loading into it the new versions of the files. To make this happen, ASP.NET uses an AppDomain feature called shadow copying.

Microsoft SQL Server 2005

Microsoft SQL Server 2005 is an unmanaged application because most of its code is still written in unmanaged C++. SQL Server 2005 allows developers to create stored procedures by using managed code. The first time a request comes in to the database to run a stored procedure written in managed code, SQL Server loads the CLR. Stored procedures run in their own secured AppDomain, prohibiting the stored procedures from adversely affecting the database server. This functionality is absolutely incredible! It means that developers will be able to write stored procedures in the programming language of their choice. The stored procedure can use strongly typed data objects in its code. The code will also be JIT compiled into native code when executed, instead of being interpreted. And developers can take advantage of any types defined in the Framework Class Library (FCL) or in any other assembly.

Microsoft Internet Explorer

When you install the .NET Framework, it installs a MIME filter (MSCorIE.dll) that is hooked into Internet Explorer versions 5.01 and later. This MIME filter handles downloaded content marked with a MIME type of "application/octet-stream" or "application/x-msdownload". When the MIME filter detects a managed assembly being downloaded, it calls the CorBindTo- RuntimeEx function to load the CLR; this makes Internet Explorer's process a host. The MIME filter is in control of the CLR and ensures that all assemblies from one Web site are loaded into their own AppDomain. Since an AppDomain can be secured, this gives an administrator the ability to grant different permission sets to code that was downloaded from different Web sites. Since AppDomains can be unloaded, the code downloaded and running from one Web site can be unloaded when the user surfs to a different Web site

Applications That Supports Add-Ins

Designing an Application That Supports Add-Ins


(Richter)

When you're building extensible applications, interfaces should be the centerpiece. way to design this application: Create a "HostSDK" strongly named assembly that defines:

1.

an interface whose methods are used as the communication mechanism between the host application and the add-in components. for the interface methods, try to use other interfaces or types defined in MSCorLib.dll. own data types

1.

The add-in developers will, define their own types in their own "Add-In assembly.
"Add-In" assembly will reference the types of "HostSDK

1.

Create a separate "HostApplication" assembly.


will reference the "Host SDK" assembly types add-in developers don't reference the "HostApplication" assembly, hence you can put out a new version of it every hour if you want to and not affect any of the add-in developers

Application That Supports Add-Ins (1/3)


HostSDK.dll using System; namespace Wintellect.HostSDK { public interface IAddIn { String DoSomething(Int32 x); } }

(Richter)

using System; AddInsTypes.dll using Wintellect.HostSDK; public sealed class AddIn_A : IAddIn { public AddIn_A() {} public String DoSomething(Int32 x) {return "AddIn_A: " + x.ToString();} } public sealed class AddIn_B : IAddIn { public AddIn_B() {} public String DoSomething(Int32 x) {return "AddIn_B: " + (x * 2).ToString();} }

Application That Supports Add-Ins (2/3)

(Richter)

using System; using System.IO; using System.Reflection; using System.Collections.Generic; using Wintellect.HostSDK; public static class Program { public static void Main() { // Find the directory that contains the Host exe String AddInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); file // Assume AddIn assemblies are in same directory as host's EXE String[] AddInAssemblies = Directory.GetFiles(AddInDir, "*.dll"); // Create a collection of usable add-in Types List<Type> AddInTypes = new List<Type>();

Application That Supports Add-Ins (3/3)

(Richter)

// Load add-in assemblies; discover which types are usable by the host foreach (String file in AddInAssemblies) { Assembly AddInAssembly = Assembly.LoadFrom(file); // Examine each publicly exported type foreach (Type t in AddInAssembly.GetExportedTypes()) { // If the type is a class that implements the IAddIn // interface, then the type is usable by the host if (t.IsClass && typeof(IAddIn).IsAssignableFrom(t)) { AddInTypes.Add(t); } } }
// Initialization complete: the host has discovered the usable add-ins

// Here's how the host can construct add-in objects and use them foreach (Type t in AddInTypes) { IAddIn ai = (IAddIn) Activator.CreateInstance(t); Console.WriteLine(ai.DoSomething(5)); }

Reflection

The System.Reflection namespace contains several types that allow you to write code that reflects over (or parses) metadata tables.
//file GExpTypes.cs Explicitly load an assembly in to this AppDomain using System; using System.Reflection; Execute this loop once for each public static class Program{ Type publicly-exported from public static void Main() { the loaded assembly String assemID = "GExpTypes"; Assembly a = Assembly.Load(assemID); foreach (Type t in a.GetExportedTypes()) { // Display the full name of the type Console.WriteLine(t.FullName); Change assemID to: "System.Data, } } }
Result: Program

Discovering Types Defined in an Assembly

version=2.0.0.0, " + "culture=neutral, PublicKeyToken=b77a5c561934e089"; Result: System.Data.Odbc.OdbcCommand Microsoft.SqlServer.Server.DataAccessKin d

System.Type objects

The System.Type type is your starting point for doing type and object manipulations. The FCL provides a few types that are derived from System.Type:

System.RuntimeType, The first time a type is accessed in an AppDomain, the CLR constructs an instance of a RuntimeType and initializes the object's fields to reflect (pun intended) information about the type. When you call non-virtual instance method System.Object.GetType() the CLR determines the specified object's type and returns a reference to its unique RuntimeType object.
System.ReflectionOnlyType, System.Reflection.TypeDelegator, a.s.o
An unique per AppDomain associated

returned by: System.Object.GetType()

AType
(loaded by CLR)

RuntimeType
instance

you can use equality and inequality operators to see whether two objects are of the same type:

o1.GetType() == o2.GetType();

created by CLR returned by GetType()

Ways to obtain a (System.)Type object (1/2)


1. 2.

calling Object's GetType() using overloaded versions of the method static System.Type.GetType(String fullNameOfTheTypeIncludingNamespaces,)

Search in calling assembly first, then in MSCorLib.dll As GetType, but the type is loaded can be reflected over but cannot be executed.

1.

static System.Type.ReflectionOnlyGetType(String fullN)

1.

etc. Once you have a reference to a Type object, you can query many of the type's properties

IsPublic, IsSealed, IsAbstract, IsClass, IsValueType, a.s.o Assembly, AssemblyQualifiedName, FullName, Module, BaseType

Ways to obtain a (System.)Type object (2/2)

Many programming languages also offer an operator that allows you to obtain a Type object from a type name

In C#, the operator is called typeof, and you use this operator typically to compare late-bound type information with early-bound (known at compile-time) type information.

// GetType returns the type of the object at run time (late-bound) // typeof returns the type of the specified class (early-bound) if (o.GetType() == typeof(FileInfo)) { ... } if (o.GetType() == typeof(DirectoryInfo)) { ... } exact match, not a compatible match: checks if the variable o refers to an object of the FileInfo type; it does not check if o refers to an object that is derived from the FileInfo type. for a compatible match: use a cast or C#'s is or as operators;

Example.
using System; using System.Reflection; ///This is a namespace namespace Reflector{ ///The main class /// <summary> /// Contains something /// </summary> class Program{ /// <summary> /// The Main method /// </summary> /// <param name="args"></param> static void Main(string[] args){ Assembly assem = Assembly.GetExecutingAssembly(); Reflector.ReflectOnAssembly(assem); Console.ReadKey(); }

/// <summary> /// Reflector class /// </summary> public class Reflector{ public static void ReflectOnAssembly(Assembly assem){ WriteLine(0, "Assembly: {0}", assem); foreach (Module m in assem.GetModules()){ WriteLine(1, "Module: {0}", m); foreach (Type t in m.GetTypes()){ WriteLine(2, "Type: {0}", t); foreach (MemberInfo mi in t.GetMembers()){ WriteLine(3, "{0}:{1}", mi.MemberType, mi); } } } } /// <summary> /// an utility class method /// </summary> /// <param name="indent"> type Int32</param> /// <param name="format"></param> /// <param name="args"></param> private static void WriteLine(Int32 indent, String format, params Object[] args){

/// <summary> /// A class to be reflected /// </summary> class SomeType{ public class InnerType { } public Int16 SomeField=0; private static string goo=null; TimeSpan ts; private void someMethod(int i){} private TimeSpan SomeProperty{ get { return new TimeSpan(); } set { ts = value; } } public static event System.Threading.ThreadStart SomeEvent; /// <summary> /// Does nothing, just for referecing some variables /// </summary> private void NoCompilerWarnings(){ SomeEvent.ToString(); goo.ToString(); } }

C:\TUDOR\Csharp\Reflection\Reflector>Reflector Assembly: Reflector, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null Module: Reflector.exe Type: Reflector.Program Method:System.String ToString() Method:Boolean Equals(System.Object) Method:Int32 GetHashCode() Method:System.Type GetType() Constructor:Void .ctor() Type: Reflector.Reflector Method:Void ReflectOnAssembly(System.Reflection.Assembly) Method:System.String ToString() Method:Boolean Equals(System.Object) Method:Int32 GetHashCode() Method:System.Type GetType() Constructor:Void .ctor() Type: Reflector.SomeType Method:Void add_SomeEvent(System.Threading.ThreadStart) Method:Void remove_SomeEvent(System.Threading.ThreadStart) Method:System.String ToString() Method:Boolean Equals(System.Object) Method:Int32 GetHashCode()

C# is more of a pure object-oriented language.


Although it is based on C++, C# is more of a pure object-oriented language. One of the primary goals of C# is safety, so many of the problems that plague programmers in C and C++ are not repeated in C#. everything in C# is an object, even a C# program or an integer value. there is a single consistent syntax used everywhere

C++: direct or indirect representation (a pointer) a safe practice: always initialize a reference when you create it: string s = "asdf"; or (better) string s = new string("asdf); //if not, possible error later: use of unassigned local variable

the identifier you manipulate is actually a reference to an object.

10.ToString(); int i=0; i.ToString(); i.GetType().ToString();//System.Int32 i = new int(); i = 1;

Value types

Unlike pure object-oriented languages such as Smalltalk, C# does not insist that every variable must be an object. the allocation of many small objects can be notoriously costly. C# goes a step beyond Java; not only are values (rather than classes) used for basic numeric types, developers can create new value types in the form of enumerations (enums) and structures (structs).

new value types have all the advantages of both value types and objects.

Common Type System (C# MSDN Training)


The Common Language Runtime includes a Common Type System (CTS) that defines a set of built-in data types that you can use to define your variables

base type:
System.ValueType for struct System.Enum for enum

base type:
System.Object

To determine the base data type of variable x : x.GetType( ).BaseType

Comparing Value and Reference Types

Built-in (base, simple) value types


Simple types are identified by means of reserved keywords. These reserved keywords are aliases for predefined structure types.

int i = 2,j=2; System.Int32.MaxValue;//2147483647 System.Int32.Equals(i, j);//True System.Int32.ReferenceEquals(i, j);//False

Structure: Equals MaxValue MinValue Parse ReferenceEquals TryParse

Enumerations
In addition to creating new classes, you can create new value types. Enumerations: a set of related values. enum UpOrDown{ Up, Down }

an

enumeration value can be used by specifying the enumeration type, a dot etc.:

The names within an enumeration are integers, whose value begins at 0. You can modify both the type of storage used for these values and the values

Enumerations: examples
namespace Enumerations {enum UpOrDown{Up, Down} class Program { enum Coin : short { Penny = 1, Nickel = 5, Dime = 10, Quarter = 25 } static void Main(string[] args) { UpOrDown coinFlip = UpOrDown.Up; // enum value as a value System.Console.WriteLine(coinFlip);// write Up // enum value as an object; System.Console.WriteLine(coinFlip.ToString());// write Up System.Console.WriteLine(Coin.Penny);// write Penny short sh=(short) (Coin.Penny) + (short)Coin.Quarter; //26 System.Console.ReadKey(); } } }

Structures

A struct (short for structure) is very similar to a class in that it can contain fields, properties, and methods. However, structs are value types,

you

cannot inherit from a struct or have your struct inherit from any class except object (although)
a struct can implement an interface, and structs have limited constructor and destructor semantics.

Structures: examples
namespace Complex { struct Complex{ double real; // a property public double Real{ get { return real; } set { real = value; } } double i; public double I { get { return i; } set { i = value; } } } class Program { static void Main(string[] args) { // constructor for structure // otherwise, unassigned, even at z.I=1; Complex z=new Complex(); z.I = 1; System.Console.WriteLine(z.I); // z.i; inaccessible, protection level System.Console.ReadKey(); } } }

C#: Array types Single dimensional

Multi dimensional
jagged

int [][] j2;

(like in Java)

j2=new int[2][];

rectangular (not in Java, could be more performant) int[,] a2; // true rectangular
int[,,] a3; // true parallelipiped

True

Rectangular and jagged arrays


//true rectangular int[] a1; int[,]a2; int[,,]a3; a1=new int[] {0,1,2,3,4,5}; a2=new int[,] {{11,12,13},{21,22,23}}; a2=new a2=new int[,] int[,] {{11,12,13},{21,22}}; {{11,12},{21,22}}; //incorrectly structured array initializer //jagged int[][] j2; int[][][] j3; //next is wrong //j2=new int[2][] {{11,12,13},{21,22,23}};

Click to edit the j2=new int[2][]; outline text format 11 12 j2[0]=new int[] {11,12,13};

13

j2[1]=new // j2 looksint[] like, {21,22,23}; but

//it is not rectangular, however; // it is jagged, like the next one:

a2

Second Outline 21 22 Level

23

11 21

12 22

13 23

//wrong number of indices // a3[0][1][2]=100; a3=new int[2,3,4]; a3[0,1,2]=100;

j2[0]=new int[] {11,12}; j2[1]=new int[] {21,22,23}; j3=new int[2][][]; j3[0]=new int[3][]; j3[1]=new int[2][]; j3[0][0]=new int[]{1,2,3,4}; // wrong number of indices // j3[0,2]=new int[]{1,2}; j3[0][1]=new int[]{1,2,3}; // j3[0,1,2]=100 j3[0][2]=new int[]{1,2};

Third Outline j2 Level Fourth Outline Level Fifth Outline

Creating and distroying objects (C# MSDN Training, module 9)

Creating Objects (C# MSDN Training, module 9)


-new (step 1) and -instance constructors (step 2) perform separate tasks, but you cannot use them separately.
This is one way for C# to help guarantee that memory is always definitely set to a valid value before it is read. (This is called definite assignment.)

class C{ public: C():i(1){} int i; };... C* q= (C*) operator new (sizeof(C));// step1: allocate, no init *q=*p;// step2: assignement C* p= new C;// alloc + init

All objects are created by using the new operator (there are no exceptions to this rule). You can do this explicitly in your code, or the compiler will do it for you.

In C++, you can allocate memory and not initialize it (by directly calling operator new). You can also initialize memory allocated previously (by using placement new). This separation is not possible in C#.

string s = "Hello"; represents: string s = new string("Hello"); int[ ] array = {1,2,3,4}; represents int[ ] array = new int[4]{1,2,3,4};

The Default Constructor (C# MSDN Training, module 9)


For an abstract class, the compiler-generated default constructor has protected access. ( Why?)

What If the Default Constructor Is Inappropriate?: Override it! (does not mean overloading!)

Public access is sometimes inappropriate. The Factory Method pattern uses a non-public constructor Procedural functions (such as Cos and Sin) often use private constructors. The Singleton pattern typically uses a private constructor Zero initialization is sometimes inappropriate. Invisible code is hard to maintain You cannot see the default constructor code (no debug!).

Overloading Constructors (1/2) (C# MSDN Training, module 9)

What is overloading? Declaring more methods with..

Overloading Constructors (2/2) (C# MSDN Training, module 9)


struct Year{ public readonly int value; public Year(int value) { this.value = value; } } struct Month{ // Or as an enum public readonly int value; public Month(int value) { this.value = value; } } struct Day{ public readonly int value; public Day(int value) { this.value = value; } } class Date{ public Date(Year y, Month m, Day d){ ccyy = y.value; mm = m.value; dd = d.value; } private int ccyy, mm, dd; } class Date{ public Date(Year y, Month m, Day d) { ... } // ISO public Date(Month m, Day d, Year y) { ... } // US public Date(Day d, Month m, Year y) { ... } // UK ... private int ccyy, mm, dd; }

Using structs or enums rather than classes for Day, Month, and Year reduces the overhead when creating a Date object.

The following code shows a simple change that would not only catch argumentorder errors but would also allow you to create overloaded Date constructors for U.K. format, U.S. format, and ISO format:

Initializing data (C# MSDN Training, module 9)

Using Initializer Lists (C# MSDN Training, module 9)

Initializer list Only in constructors public void Init():this(0,0){} No recursion public C(int x):this(0){}

Avoid Duplicate Initializations


public Date( ){ Init(1970, 1, 1); } public Date(int year, int month, int day){ Init(day, month, year); } private void Init(int year, int month, int day){ ccyy = year; mm = month; dd = day; }

public Date( ) : this(1970, 1, 1){} public Date(int year, int month, int day){ ccyy = year; mm = month; dd = day; }

Init method, does not work for readonly fields!

Allways works, no need for extra Init method!

Readonly variables and constants

(C# MSDN Training, module 9)

Using Readonly Variables You can qualify a field as readonly in its declaration, as follows: readonly int nLoopCount = 10; You will get an error if you attempt to change the value at run time.

. Using Constant Variables A constant variable represents a constant value that is computed at compile time. Using constant variables, you can define variables whose values never change, as shown in the following example: const int speedLimit = 55;

Initializing readonly variables


Readonly Fields Must Be Initialized
1. 2. 3.

(C# MSDN Training, module 9)

Implicitly to zero, false or null Explicitly at their declaration in a variable initializer Explicitly inside an instance constructor

1. Implicitely: Not very useful!

class Readonly{ private readonly int[] ri; private readonly int[] rd=new int[2]; private readonly int[] rc; public Readonly(int i) { rc = new int[i]; } void m() { rd[0] = 1; vectors rd, rc are rc[0] = 1; readonly, but their components are not // ri = new int[2]; // rd= new int[2]; error: // rc = new int[2]; a readonly cannot be assigned to } (except in a } -constructor or -variable initializer)

2. variable initializer This is really just convenient shorthand. The compiler conceptually rewrites a variable initialization (whether it is readonly or not) into an assignment inside all constructors.

3. Constructor advantage: you can use constructor parameters in the new expression.

Constructor for a struct (1/3)

(C# MSDN Training, module 9)

The Compiler Always generates a default constructor, regardless of whether you declare constructors yourself (unlike the situation with classes) Default constructor automatically initialize all fields to zero. The Programmer Can declare constructors with one or more arguments. Declared constructors do not automatically initialize fields to zero. Can never declare a default constructor. Can never declare a protected constructor.
struct SPoint{ public SPoint(int x, int y) { ... } ... static void Main( ){ // Okay SPoint p = new SPoint( ); Spoint q; } }

SPoint() always created, for a struct CPoint() creation supressed, for a class

class CPoint{ public CPoint(int x, int y) { ... } ... static void Main( ){ // Compile-time error CPoint p = new CPoint( ); } }

Both creates new struct values on the stack (using new to create a struct does not acquire memory from the heap). There is no way to change this behavior. --For p, initializes the fields to zero. --For q, creates a struct value on the stack but does not initialize any of the fields
(so any field must be definitely assigned before it can be referenced).

Constructor for a struct (2/3)


struct SPoint{ public int x, y; static void Main( ) { SPoint p1; p1.y = 2; Console.WriteLine(p1.y); // ok Random r = new Random(); goto L; M: Console.WriteLine(p1.x); L: if(r.Next(1000)<2000)p1.x = 1; goto M; } }

(C# MSDN Training, module 9)

no initialization of struct fields, so any field must be definitely assigned before it can be referenced

Initialization, OK

Error: use of possibly unassigned field x Note: in fact, x is always assigned

Constructor for a struct (3/3)


You Must Initialize All Fields in a struct
class CPoint{ private int x, y; public CPoint(int x, int y) { /*nothing*/ }// Okay. } // Okay: initialized when declared

(C# MSDN Training, module 9)

In a class, compiler ensures that x and y are initialized to zero.

struct SPoint1 { private int x = 0, y = 0; public SPoint1(int x, int y) { } }

// Okay: initialized in constructor

// Compile-time error: SPoint3.y must be fully assigned before control is returned to the caller

struct SPoint2{ private int x, y; public SPoint2(int x, int y){ this.x = x; this.y = y; } }

struct SPoint3 { private int x, y; public SPoint3(int x, int y) { this.x=0; // this.y=0; } }

Private constructors and static methods


(C# MSDN Training, module 9)

declaring a constructor in the Math class: prevent the compiler from generating the default constructor, constructor as private, stop Math objects from being created. prevents Math from being used as a base class.

as a static method, the syntax for using Cos becomes: Simpler (Math.Cos()) Faster (no longer need to create a new Math object.)

Singleton Pattern
(C# MSDN Training, module 9)

Singleton pattern: ensure a class with only has one instance, and provide a global point of access to it private constructor and static methods is sometimes suggested as a way to implement the Singleton pattern. canonical implementation of the Singleton pattern: create a static method that gives access to the single instance, this instance is then used to call instance methods.

With a private constructor and all methods static, there is no instance at all.

Singleton Pattern, an example


Give class Singleton{ the public static Singleton Give(){ singleton if (!created) { created = true; theSingleton = new Singleton(); } return theSingleton; processing } the public void m(){x++;} A field: no need to be static singleton public int X{ get{return x;} Private constructor set{x=value;} A flag: true after the singleton } creation private Singleton(){} private int x=0;// not a static member! A reference to the only one instance private static bool created = false; private static Singleton theSingleton; } class MainProg{ public static void Main(string[] args) { //Singleton s = new Singleton(); Singleton s = Singleton.Give();// Singleton p = Singleton.Give();// s.m(); p.m(); p.m(); p.m(); System.Console.WriteLine(s.X == p.X); } } error: not accessible, due to its protection level in fact, the same object

true!

Static Constructors

(C# MSDN Training, module 9)

C# is a dynamic language. When the Common Language Runtime is running a Microsoft .NET program, it often encounters code that uses a class that has not yet been loaded. In these situations, execution is momentarily suspended, the class is dynamically loaded, and then execution continues.

The most common use : This is because when you initialize a static field directly at its point of declaration, the compiler conceptually converts the initialization into an assignment inside the static constructor. In other words

class Example{ private static W w = new W( ); }


is effectively converted by the compiler into

class Example{ static Example( ) { w = new Wibble( ); } private static W w; }

Destroying Objects Destroying a C# object is also a tw o-step process: 1. De-initialize the object.
converts the object back into raw memory. It is done by the destructor or the Finalize method. This is the reverse of the initialization performed by the constructor. You can control what happens in this step by writing your own destructor or finalize method. 2. The raw memory is deallocated; that is, it is given back to the memory heap.

This

This is the reverse of the allocation performed by new. You cannot change the behavior of this step in any way .

Scope and Lifetime


The

Lifetime of a Local Value Is Tied to the Scope in Which It Is Declared


Short

lifetime (typically) Determinisitic creation and destruction


The
A

Lifetime of a Dynamic Object Is Not Tied to Its Scope


longer lifetime A non-deterministic destruction

Values
struct Point { public int x, y; } enum Season { Spring, Summer, Fall, Winter } class Example { void Method() { for (int i = 0; i < 10; i++) The name does not exists in the current context { int x = 42; Point p = new Point(); Season s = Season.Winter; } x = 42; // Compile-time error p = new Point(); // Compile-time error s = Season.Winter; // Compile-time error } }

Objects lifetime

class Example { void Method(){ for (int i = 0; i < 10; i++) { Example eg = new Example( ); } // eg is out of scope // Does eg still exist? // Does the object still exist? } } Longer lifetimes Because the life of an object is not tied to the method that creates it, an object can exist well beyond a single method call

Non-deterministic destruction An object is created when you create it, but, unlike a value, it is it not destroyed at the end of the scope in which it is created. The creation of an object is deterministic, but the destruction of an object is not. You cannot control exactly when an object will be destroyed.

Garbage Collection

You Cannot Destroy Objects in C# C# does not have an opposite of new (such as delete) This is because an explicit delete function is a prime source of errors in other languages Forgetting to destroy objects. Attempting to destroy the same object more than once. Destroying an active object. (dangling pointer problem:

Dangling pointers arise when an object is deleted or deallocated without modifying the value of the pointer so that the pointer still points to the memory location of the deallocated memory. )

Garbage Collection Destroys Objects for You It finds unreachable objects and destroys them for you It finalizes them back to raw unused heap memory It typically does this when memory becomes low

Managed/unmanaged resources

Managed resource (GC free them implicitly):

Resource which is part of an assembly. native .Net objects, (arrays etc.) Unmanaged heap memory blocks (native resource),

Unmanaged resources (GC doesn't free them implicitly):


allocated with System.Runtime.InteropServices.Marshal class suppose you have to open a database connection from within a class. the database connection instance is an unmanaged resource encapsulated within this class it should be released as soon as you are done with it. in such cases, you'll need to free the memory occupied by the unmanaged resources explicitly

file handles, database connections (native resource), etc.


.NET garbage collector (System.GC)


manages the memory of managed objects (native .NET objects) it does not manage, nor is it directly able to clean up unmanaged resources Briefly, the GC works as shown below:
It searches for managed objects that are referenced in managed code. It then attempts to finalize those objects that are not referenced in the code. Lastly, it frees the unreferenced objects and reclaims the memory occupied by them.

The GC maintains lists of managed objects arranged in "generations."


A generation is a measure of the relative lifetime of the objects in memory. Recently created objects are stored in lower generations compared to those created earlier in the application's life cycle. Longer-lived objects get promoted to higher generations. GC runs much more frequently to clean up objects in the lower generations than in the higher ones (because applications tend to create many short-lived objects compared to relatively few long-lived objects)

Example: Garbage Collection (1/2)


public class NoMemoryLeak{ class Image{ public Image(){ if((count1-count2)*(count-count1)<0){ oldCount=count; System.Console.WriteLine("New: {0}, {1}, {2}",count2, count1, count); } count2=count1; count1=count; count++; } ~Image(){ if((count1-count2)*(count-count1)<0){ System.Console.WriteLine("GC: {0}, {1}, {2}",count2, count1, count); Here, an attribute System.Console.WriteLine("GC: {0}",count-oldCount); } count2=count1; count1=count; count--; } //.. static long count=0; static long count1=1; static long count2=0; static long oldCount=0;

Example: Garbage Collection (2/2)


public static void Main(){ NoMemoryLeak ml=new MemoryLeak(); while(true) ml.m(); } void m(){Image im=new Image();} }
With the attribute: private System.Drawing.Bitmap img = new System.Drawing.Bitmap (@"D:\tudor\Csharp\andreut.bmp"); Results: New: 4, 3, 4 GC: 131, 132, 131 GC: 127 . New: 4, 3, 4 GC: 130, 131, 130 GC: 126 New: 4, 3, 4 GC: 131, 132, 131 GC: 127

Run on a computer having 1.00 GB of RAM GC does garbage collection

250KB

count

With System.GC.Su ppress.Finalize (im) here ~Image() is suppressed, but GC does its task. No memory leak appears

With the attribute: private double d =0; Results: New: 1, 0, 1 GC: 17356, 17357, 17356 GC: 17355 New: 172112, 172111, 172112 GC: 172249, 172250, 172251 GC: 139 New: 1020992, 1020991, 1020992 GC: 1109040, 1109041, 1109042 GC: 88050 New: 1163843, 1163842, 1163843 GC: 1165367, 1165368, 1165369 GC: 1526

around 32MB

Number of finalized objects

count

Garbage Collection Algorithm (J. Richter, CLR via C#)

When a garbage collection starts, GC assumes that all objects in the heap are garbage Marking phase:

Click to edit the compact phase outline text format the collector traverses the heap linearly looking for contiguous blocks of

walk up the threads stack, checking all of the roots;

unmarked (garbage) objects.

large free contiguous blocks are shifted down in memory to compact the heap.

Second Outline Level Click to edit the Third Outline outline text format Level Second Outline Fourth Level Outline Third Outline Level

Garbage Collections and Debugging (1/2)


using System; using System.Threading; public static class Program { public static void Main() { // Create a Timer object that knows to call our TimerCallback // method once every 2000 milliseconds. Timer t = new Timer(TimerCallback, null, 0, 2000); Console.ReadLine(); // ************* } private static void TimerCallback(Object o) { // Display the date/time when this method got called. Console.WriteLine("In TimerCallback: " + DateTime.Now); // Force a garbage collection to occur for this demo. GC.Collect(); }

Garbage Collections and Debugging (2/2)

>csc /debug TimerCallback method is called just once! garbage collection reclaims the memory for

object; this stops the timer

the Timer

>csc /debug+
TimerCallback method will get called repeatedly JIT compiler compiles the method, artificially

extending the lifetime of all variables until the end of the method. the Timer object will survive the collection,

Replacing //******** by
t=null; (no effect, JIT is an optimizing compiler) t.Dispose(); Timer survives, regardless /debug[+/-]

Using Finalization to Release Native Resources

Basically, the type implements a method named Finalize, a special kind of method requiring a special syntax. internal sealed class SomeType { // This is the Finalize method ~SomeType() { // CODE } }

Finalization is a mechanism offered by the CLR that allows an object to perform some graceful cleanup prior to the garbage collector reclaiming the object's memory Any type that wraps a native resource, such as a file, network connection, socket, mutex, or other type, must support finalization.

Compiler generates: protected void override Finalize( ){ try{ // CODE }finally{ base.Finalize()} }

Finalize looks like but it does not work like a C++ destructor,( in C++ object are deterministically destroyed)
earlier versions of the C# called this method a destructor in version 2 of the C# a method using this syntax is now officially called a finalizer.

If a type that wraps a native resource fails to define a Finalize method, the native resource won't be closed and will cause a resource leak that will exist

Finalization Internals (1/3)


(J. Richter, CLR via C#)

the new operator allocates the memory from the heap. If the object's type defines a Finalize method, a pointer to the object is placed on the finalization list just before the type's instance constructor is called

Finalization Internals (2/3)

(J. Richter, CLR via C#)

E,I,J garbage objects were resurected (they are still reachable)

Finalization Internals (3/3)

(J. Richter, CLR via C#)

Rules for finalizers


You should note the following points should when implementing finalizers: Finalizers should always be protected, (so that the method cannot be called from the application's code directly) and at the same time, it can make a call to the base.Finalize method Finalizers should release unmanaged resources only. The framework does not guarantee that a finalizer will execute at all on any given instance. Never allocate memory in finalizers or call virtual methods from finalizers. Avoid synchronization and raising unhandled exceptions in the finalizers. The execution order of finalizers is non-deterministicin other words, you can't rely on another object still being available within your finalizer. Do not define finalizers on value types. Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resourcesand if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether. Finalize() is a non-explicit way to clean up resources. Because you can't control when (or even if) the GC calls Finalize, you should treat destructors only as a fallback mechanism for releasing unmanaged resources. Instead, the approved way to release unmanaged resources is to make your class inherit from the IDisposable interface and implement the Dispose() method.

Releasing unmanaged resources : The Dispose Pattern (1/3) Checking dispose flag allow

public class Base : System.IDisposable{ protected virtual void Dispose(bool disposing) { if (!isDisposed) { if (disposing) { // Code to dispose managed resources // held by the class } // Code to dispose unmanaged resources // held by the class isDisposed = true; } } private bool isDisposed = false; ~Base(){ Dispose(false); }

Dispose to be called multiple times without raising errors. Boolean disposig indicates whether Click to edit the or not the private dispose method was called by: the user (true) or outline text format by the Garbage collector (false)

Second Outline Level

Third disposed Outline Level flag the Indicate that Dispose was called by Fourth GC not by the user, we only want to clean up Outline unmanaged resources Level

The Dispose Pattern (2/3)


public void Dispose() { Dispose(true); System.GC.SuppressFinalize(this); } //other processing methods public void DoSomething(){ if(isDisposed) throw new System.Exception(); //do something } }

Implements interface member System.Idisposable.Dispose

if the user calls Dispose() then you can stop the GC from calling Dispose function in the finalizer because this is unneccessary never change the order of calls in the finalization context (first Dispose(true) and then GC.SupressFinalize)

if you implement Dispose() check the "disposed" flag in other places in your class, so that you throw an exception if your caller tries to do something dumb like this: b.Dispose(); b.DoSomething();

The Dispose Pattern (3/3)


The boolean disposing:. indicates whether or not the private dispose method was called by the user or by the Garbage collector There is an important reason for this. Managed resources: If the user calls Dispose then you know that all managed resources pointed to by your object must still be alive i.e. not garbage collected because your object still has a reference to them so they will not be collected and someone must have had a reference to your object to call the public Dispose() method. If the GC called Dispose then you cannot be sure that the objects which your object is referencing have not already been garbage collected, so you should not call any methods on them. Unmanaged resources: You can be sure that unmanaged resources have not been Garbage collected because the GC does not know about them so it is safe to clean them up.

Note that the derived class does The Dispose Pattern in derived class
http://www.devx.com/dotnet, Joydip Kanjilal

public class Derived : Base public void IDisposable.Dispose() { protected override void Dispose(bool disposing) { if (disposing) { // Code to cleanup managed resources held by the class. } // Code to cleanup unmanaged resources held by the class. base.Dispose(disposing); } }

not re-implement

make sure resources in the base class are disposed correctly.

Example: Dispose

(see)

managed wrapper around another manged wrapper (Bitmap img)

public class Base : System.IDisposable{ protected virtual void Dispose(bool disposing) { //. if (disposing) { // Code to dispose managed resources // held by the class if (img!=null)img.Dispose(); // public void DoSomething(Graphics g, int i, int j) { if (isDisposed) throw new System.Exception(); g.DrawImage(img, i, j); } private System.Drawing.Bitmap img = new Bitmap(@"D:\tudor\Csharp\andreut.bmp"); // }

public class Draw :System.Windows.Forms.Form{ [STAThread] public static void Main() { Application.Run(new Draw()); } protected override void OnPaint(PaintEventArgs pp){ Graphics g = this.CreateGraphics(); b.DoSomething(g,10,10); b.Dispose(); //b.DoSomething(g,10,10); } Base b= new Base(); }

//System.Exception has thrown

Rules for implementing Dispose

http://www.devx.com/dotnet, Joydip Kanjilal

Note the following points when implementing disposable types: Implement IDisposable on every type that has a finalizer Ensure that an object is made unusable after making a call to the Dispose method. In other words, avoid using an object after the Dispose method has been called on it. Call Dispose on all IDisposable types once you are done with them Allow Dispose to be called multiple times without raising errors. anytime you implement the Dispose function you also want to make sure that you call the Dispose function from your objects finalizer (~Base()). This is because you cannot force someone to call your Dispose function, so if they do not call it then you need to make sure the GC calls it instead. Suppress later calls to the finalizer from within the Dispose method using the GC.SuppressFinalize method Avoid creating disposable value types Avoid throwing exceptions from within Dispose methods
using statement, not directive MustDispose obj = new MustDispose; try { // use the object } finally { if (obj != null) ((IDisposable)obj).Dispose(); } or using (MustDispose obj = new MustDispose) { // use the object } The compiler will dispose the obj object now !

Example: System.IO.FileStream class (read/write bytes) When a FileStream object is constructed: a file handle is saved in a SafeFileHandle object, and a reference to this object is maintained via a private field in the FileStream object. using statement using System;

Using a Type That Implements the Dispose Pattern


(J. Richter, CLR via C#)

using System.IO; which calls Dispose on public static class Program{ the SafeFileHandle object, public static void Main(){ which ends up calling the // Create the bytes to write to the temporary file. Win32 CloseHandle Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 }; // Create the temporary file. function, FileStream fs = new FileStream("Temp.dat", FileMode.Create); using(fs){ // Write the bytes to the temporary file. fs.Write(bytesToWrite, 0, bytesToWrite.Length); Close method isn't } //dispose by compiler or officially part of the // Explicitly close the file when finished writing to it. dispose pattern; // fs. Dispose();// or fs.Close() // Delete the temporary file. some types will offer it File.Delete("Temp.dat"); // }

calls the Dispose(true)

and some won't.

Closing/Disposing a Data Base Connection


Don't forget you can use the using(){} construct to using System; auto-magically call Dispose: using System.Data; using System.Data.OleDb; OleDbConnection oledbconn=new OleDbConnection(@"Provider=Microsoft.Jet.OleDb.4.0;Data Source=d:\tudor\Csharp\OLEDB\db1.mdb"); using(oledbconn){ OleDbCommand cmd=new OleDbCommand("SELECT * FROM table1 ORDER BY first",oledbconn); OleDbDataReader outData=null; oledbconn.Close(), called after try block cmd.CommandType=CommandType.Text; hence oledbconn.Open() allowed here try{ oledbconn.Open(); outData=cmd.ExecuteReader(); while(outData.Read()){ Console.WriteLine("first: {0} last:{1} \n", outData["first"], outData["last"]); } }catch(Exception e){Console.WriteLine("Exception: {0}",e.Message);} oledbconn.Dispose(), called after try finally{oledbconn.Close();} block oledbconn.Open(); hence oledbconn.Open() not allowed } here: System.InvalidOperationException oledbconn.Open();

Closing/Disposing a FileStream
using System; using System.IO; string path = @"d:\tudor\csharp\temp\MyTest.txt"; // Delete the file if it exists. if (File.Exists(path)) {File.Delete(path); //Create the file. using (FileStream fs = File.Create(path)){ byte[] info = new UTF8Encoding(true).GetBytes(Tudor); fs.Write(info, 0, info.Length); } //Open the stream and read it back. using ( Filestream fs = File.OpenRead(path) { byte[] b = new byte[1024]; UTF8Encoding temp = new UTF8Encoding(true); while (fs.Read(b, 0, b.Length) > 0){ Console.WriteLine(temp.GetString(b)); } }

Note that fs scope is inside using block; Compiler prevets from usig fs outside the using block, that is after its disposing

Classes and inheritance

Classes and inheritance

(C# MSDN Training, module 9)

A C# class can extend at most one class. Note: a struct does not support inheritance.

A derived class inherits everything from its base class except for the base class constructors and destructors. Looks like private inheritance in C+ + A derived class cannot be more accessible than its base class. C# has no private inheritance; all class Example{ inheritance is public. private class NestedBase { } public class NestedDerived: NestedBase { } // Error } Constructor declaration: To call a base class constructor from the derived class constructor, use the constructor initializer (:base) keyword base. C(...): base() {...} C(){} means C(...): base() {...} there is no way for a derived class to Constructor acces rules call the base class constructor. class NonDerivable{ private NonDerivable( ) { ... } } class Impossible: NonDerivable{ public Impossible( ) { ... } // Compile-time error }

Click to edit the outline text format

Second Outline Level Third Outline Level Fourth Outline Level

Scoping an identifier
You can use the keywords base and this to also qualify the scope of an identifier. This can be useful, since a derived class is permitted to declare members that have the same names as base class members. class Token{ protected string name; } class CommentToken: Token{ int i=0; public void Method(string name, int i){ base.name = name; this.i=i; } } Unlike in C++, the name of the base class, such as Token in the example is not used (Token::name). The keyword base unambiguously refers to the baseclass because in C# a class can extend one base class at most.

Protected members
Methods of a derived class can only access their own inherited protected members. They cannot access the protected members of the base class through references to the base class. class Token{protected string name;} class CommentToken: Token{ void AlsoFails(Token t){ Console.WriteLine(name); //OK Console.WriteLine(t.name); // Compile-time error } }

Many coding guidelines recommend keeping all data private and using protected access only for methods. protected access modifier cannot be used in a struct (structures does not support inheritance)

Versioning, explicit virtual chains, broken chains

Implementing methods

You can redefine the methods of a base class in a derived class when the methods of the base class have been designed for overriding. A virtual method specifies an implementation of a method that can be polymorphically overridden in a derived class.
You cannot declare virtual methods as static (polymorphism works on objects, not on classes). You cannot declare virtual methods as private (they cannot be polymorphically overridden in a derived class).

An override method specifies another implementation (or version) of a virtual method.


You can only override identical inherited virtual methods. You must match an override method with its associated virtual method

the same acces level the same return type the same signature

You can override an override method. You cannot implicitly declare an override method as virtual. You cannot declare an override method as static or private.

Using new to broke a chain (hide methods)


namespace MyVeryFirstProgram { using System;

The program displayes: DDBB A M() B M() C M() M() M() Broken chain for M() M()

class A { public virtual void M() { Console.Write("A"); } } class B : A { public override void M() { Console.Write("B"); } } class C : B { new public virtual void M() { Console.Write("C"); } } class D : C { public override void M() { Console.Write("D"); } static void Main() { D d = new D(); C c = d; B b = d; A a = d;

D M() M()

Fragile Base Class Problem

Fragile base class problem


Changes in base class implementation, causing a problem in the subclass.

An extension: class DerivedClass extends BaseClass { public void display() { //overriding counter++; // new

Java example:

System.out.println("DerivedClass.display()");//
modified } }

class BaseClass { public void display() { System.out.println("BaseClass.display()"); } public void callMultipleTimes(int n) { for (int c1 = 0; c1 < n; c1++) { display(); } } } public class Fragile{ public static void main(String args[] ){ BaseClass b= new BaseClass(); b.callMultipleTimes(3);

Click to edit the outline text format

Changes, to count Second Outline displays Level

public int counter=0; }

What if BaseClass changes?

public class FragileExtension{

public static void main(String args[] ){ DerivedClass b= new DerivedClass();

Third Outline Level Fourth Outline FragileExtension displays 3 and 6 etc. Level
b.callMultipleTimes(3); b.callMultipleTimes(3); System.out.println(b.counter);

Base class changes causing problems


A new version of the base class
class BaseClass { public void display() { System.out.println("BaseClass.display()"); } public void callMultipleTimes(int n) { for (int c1 = 0; c1 < n; c1++) { System.out.println("BaseClass.display()"); } } }

Click to edit the outline text format

Second Outline The same Level .class FragileExtension


(no need for compilation ), with the new version of BaseClass.class displays 0 and 0 etc.! No counting!

Change: no call to display()

Third Outline Level Fourth Outline Level

Explanation: lack of the hierarchy contract


How to forbid some changes? ?????????????????? C# approach for fragile base class problem

Exercise: Spot the bugs


class Base Error: 'Base.Epsilon()': virtual or abstract members { cannot be private public void Alpha() { ... } public virtual void Beta() { ... } public virtual void Gamma(int i) { ... } public virtual void Delta() { ... } private virtual void Epsilon() { ... } Error: 'Derived.Alpha()': cannot override inherited member 'Base.Alpha()' because it is not marked virtual, } abstract, or override class Derived : Base { Error: 'Derived.Beta()': cannot change access modifiers when overriding 'public' inherited member 'Base.Beta()' public override void Alpha() { ... } protected override void Beta() { ... } public override void Gamma(double d) { ... } Error: 'Derived.Gamma(double)': no suitable method public override int Delta() { ... } found to override }
Error: 'Derived.Delta()': return type must be 'void' to match overridden member 'Base.Delta()'

you must be very careful when adding or modifying members of a type if that type is used as a base type.
using System; using System.Reflection; [assembly:AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] [assembly:AssemblyDescription ("This assembly contains CompanyA.Phone type")] namespace CompanyA{ public class Phone{ public void Dial(){ Console.WriteLine("Phone.Dial"); // Do work to dial the phone here. } } }

Dealing with virtual methods when versioning types(1/5)

>csc /t:library Phone1000.csc And see its metadata with >ildasm Phone1000.dll

Dealing with virtual methods when versioning types(2/5)


using System; using System.Reflection; [assembly: AssemblyVersion("1.0.0.0")] [assembly:AssemblyDescription("This assembly contains CompanyB.BetterPhone type")] namespace CompanyB { public class BetterPhone : CompanyA.Phone { public new void Dial() { Console.WriteLine("BetterPhone.Dial means"); base.Dial(); EstablishConnection(); } protected virtual void EstablishConnection() { Console.WriteLine("BetterPhone.EstablishConnection"); // Do work to establish the connection. } } }

Warning, if new is missing (hides an inheritted)

>csc /t:library /r:Pone1000.dll BetterPhone1000.csc And see its metadata with >ildasm BetterPhone1000.dll

Dealing with virtual methods when versioning types(3/5)


using System.Reflection; [assembly: AssemblyVersion("0.1.1.0")] [assembly:AssemblyDescription("This assembly works with Phone 1.0.0.0, BetterPhone 1.0.0.0")] namespace VersioningTypes{ class Program { static void Main(string[] args){ CompanyB.BetterPhone bph=new CompanyB.BetterPhone(); bph.Dial(); } } }

>csc /t:exe /r:Pone1000.dll,BetterPhone1000.dll app.csc And see its metadata with >ildasm app.exe Run with >app.exe

Results: BetterPhone means: Phone.Dial BetterPhone.EstablishConnexion

Dealing with virtual methods when versioning types(3/5) What if a new version of Phone
(2.0.0.0) has its own using System; EstablishConnection using System.Reflection; method? [assembly:AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("2.0.0.0")] [assembly:AssemblyDescription("This assembly contains new version of CompanyA.Phone type")] namespace CompanyA { public class Phone { public void Dial () { Console.WriteLine("Phone.Dial"); // Do work to dial the phone here. EstablishConnection(); } protected virtual void EstablishConnection() {
Console.WriteLine("Phone.EstablishConnection"); // Do work to establish the connection. } } }

Dealing with virtual methods when versioning types(5/5)


Changing Better Phone to:
Class BetterPhone{ new Dial() protected new virtual void EstablishConnection() { Hard to find a significance! Class BetterPhone{ new Dial() protected override void EstablishConnection() { Phone.Dial semantics is OK but needs a different connection Delete Phone.Dial()+override Class BetterPhone{ Dial{} deleted protected override void EstablishConnection() { Phone.Dial replaced and Phone. Econn needs some completion

gives results:
BP.Dial P.Dial P.Econn BP.Econn BP.Dial P.Dial BP.Econn BP.Econn

P.Dial BP.Econn

Sealed classes

Interfaces

(C# MSDN Trainin, module 10)

Abstract classes

(C# MSDN Training, module 10)

Classes and properties (1/2)

Single inheritance: one base class and as many interfaces as you want class Derived: Base, IPersistent, IPrintable{ } Properties: a way to expose an internal data element of a class in a simple and intuitive manner while retaining the control over the way the data is used. C#: the first language to offer direct support for properties (in C++ Builder and Delphi, this feature is an extension of the languages they supported, C++ and Object Pascal, respectively )

using System; class Person{ public int Age{ set{ if ((0<= value) && (value<=200))age=value; // && is conditional and! else System.Console.WriteLine("Wrong age for a person!"); } get{return age;} } private int age; } public class MainClass{ public static void Main(){ Person p= new Person(); p.Age=25; //OK, even if age is private! System.Console.WriteLine(p.Age); p.Age=201; // The value is invalidated by set function System.Console.ReadLine(); } }

Properties
Familiar concept to Delphi and Visual Basic users Properties within a structure enable the client to read, write and compute values with the use of accessors. Unlike fields, they do not designate storage space. Hence, a property cannot be passed as a ref or out argument. public class Button{ Benefits: see [1] public string Caption{ -The C# code is more readable than Java/C++ property implementation get{ (using String getCaption() and void setCaption(String value) return caption; methods) } Refined accessibility: rw, r or w instead of public/private set{ Easy to change the name of the property: just one line caption=value; More compact code (setters and getters placed together) } } Arguments against: private string caption; -you don't know if you're manipulating a field or a property with this } syntax, but in a well designed systems, classes do not have public fields anyway public class Appl{ public static void Main(){ Button B=new Button(); B.Caption="Button1"; System.Console.WriteLine(B.Caption); } }

C#: checked and unchecked mathematical operations


class C{ public static void Main(){ int i= int.MaxValue; System.Console.WriteLine(i+1); // -2147483648, Why? System.Console.WriteLine((long)(i+1)); // -2147483648 System.Console.WriteLine((long)i+1); // 2147483648 System.Console.WriteLine(unchecked(i+1)); // -2147483648 System.Console.WriteLine(checked(i+1)); checked {System.Console.WriteLine(i+1);} //or //results in an

// Unhandled Exception: System.OverflowException: // Arithmetic operation resulted in an overflow System.Console.ReadLine(); }


} Note: all operations checked:

> csc /checked+ source.cs

Methods, parameters and arguments


No functions: every piece of code belongs to a given class Functions can have four types of parameters

Input parameters (by default) Output parameters (use modifier out); Reference parameters (modifier ref) Arrays parameters, allowing a variable number of arguments (modifier params)

The modifiers out and ref must be specified for arguments too!

Operator Overloading

All operators are public static methods and their names follow a particular pattern (operatorop) Overloading arithmetic operators: all arithmetic operators return an instance of the class and manipulate objects of the class
public struct Time{ public Time(int minutes) : this(0, minutes){} public Time(int hours, int minutes){ this.hours = hours; this.minutes = minutes; Normalize( ); } // Arithmetic public static Time operator+(Time lhs, Time rhs){ return new Time(lhs.hours + rhs.hours,lhs.minutes + rhs.minutes); } public static Time operator-(Time lhs, Time rhs){ return new Time(lhs.TotalMinutes( ) rhs.TotalMinutes( )); } // Helper methods private void Normalize( ){ if (hours < 0 || minutes < 0) { throw new ArgumentException("Time too small"); } hours += (minutes / 60); minutes %= 60; } private int TotalMinutes( ){ return hours * 60 + minutes; } private int hours; private int minutes; }

Relational operator overloading

Relational Operators Must Be Paired (with their logical antonym) < and > l<= and >= l== and != Overloading == and != Overriding Equals Overriding GetHashCode For consistency, create a Compare method first and define all the relational operators by using Compare.
// Inherited virtual methods (from object) public override bool Equals(object obj){ return obj is Time && Compare((Time)obj) == 0; } public override int GetHashCode( ){ return TotalMinutes( ); } // Helper methods private int Compare(Time other){ int lhs = TotalMinutes( ); int rhs = other.TotalMinutes( ); int result; if (lhs < rhs)result = -1; else if (lhs > rhs)result = +1; else result = 0; return result; } ...

public struct Time{ ... // Equality pair --------------------public static bool operator==(Time lhs, Time rhs){ return lhs.Compare(rhs) == 0; } public static bool operator!=(Time lhs, Time rhs){ return lhs.Compare(rhs) != 0; }//--------------------------------------------------// Relational public static bool operator<(Time lhs, Time rhs){ return lhs.Compare(rhs) < 0; } public static bool operator>(Time lhs, Time rhs){ return lhs.Compare(rhs) > 0; } //-----------------------------------------------public static bool operator<=(Time lhs, Time rhs){ return lhs.Compare(rhs) <= 0; } public static bool operator>=(Time lhs, Time rhs){ return lhs.Compare(rhs) >= 0; }

Overloading logical operators


Logical Ops cannot overload the logical operators && and || directly. they are evaluated in terms of the &, |, true , and false operators. If variables x and y are both of type T, the logical operators are evaluated as follows: x && y is evaluated as T.false(x) ? x : T.&(x, y) x || y is evaluated as T.true(x) ? x : T.|(x, y)

Overloading conversion operators


Implicit Conversion Is Safe (is guaranteed not to lose information) int intVar = 99; float floatVar; floatVar = intVar; Explicit Conversion Requires a Cast
(are not considered to be safe by the compiler, a cast is needed)

float floatVar = 99.9F; int intVar; intVar = (int)floatVar;

Programmer can define implicit and explicit conversion operators


If a conversion operator could throw an exception or return a partial result, make it explicit. If a conversion is guaranteed to work without any loss of data, you can make it implicit.

Design guidelines for consistency: String conversion operator should override the ToString method ( which should perform the same function)
public struct Time{ ... // Conversion operators // safe public static implicit operator int (Time t1){return t1.TotalMinutes( );} public static implicit operator string (Time t1){return t1.ToString( );} // overriding ToString recomended //unsafe public static explicit operator Time (int minutes){return new Time(0, minutes);} public static explicit operator Time (float minutes){return new Time(0, (int)minutes);} public static explicit operator float (Time t1){return t1.TotalMinutes( );} // overriding inherited virtual methods (from Object) public override string ToString( ){return String.Format("{0}:{1:00}", hours, minutes);} ... }

Delegates and Events


Scenario: Power Station

In a power station, the temperature of the nuclear reactor must be kept below a critical temperature. If the temperature rises significantly, various pumps need to be started The software controlling the working of the nuclear reactor must start the appropriate pumps

Possible Solutions
1.

The software driving the coolant pumps could constantly measure the temperature of the nuclear core and increase the flow of coolant as the temperature requires. The component monitoring the core temperature could start the appropriate coolant pumps every time the temperature changes. the frequency with which the temperature must be measured needs to be determined. there may be many dozens of pumps and controllers that need to be alerted about each temperature change. The programming required to achieve this could be complex and difficult to maintain, especially if there are different types of pumps in the system that need to be alerted indifferent ways.

2.

Drawbacks
1.

2.

Analysing the problem

Existing Concerns

There may be several types of pumps, supplied by different manufacturers Each pump could have its own method for activation To add a new pump, the entire code will need to change A high overhead cost will result with every such addition Use delegates in your code
public class CoreTempMonitor{ public void Add(object pump){pumps.Add(pump);} public void SwitchOnAllPumps(){ foreach (object pump in pumps) { if (pump is ElectricPumpDriver) ((ElectricPumpDriver)pump).StartElectricPumpRunning(); if (pump is PneumaticPumpDriver) ((PneumaticPumpDriver)pump).SwitchOn(); } ... ... private ArrayList pumps = new ArrayList(); } public class ExampleOfUse{ public static void Main( ){ CoreTempMonitor ctm = new CoreTempMonitor(); ElectricPumpDriver ed1 = new ElectricPumpDriver(); ctm.Add(ed1); PneumaticPumpDriver pd1 = new PneumaticPumpDriver(); ctm.Add(pd1); ctm.SwitchOnAllPumps(); } }

Future Concerns

A Solution

// own software driver for each type of pump public class ElectricPumpDriver{ ... public void StartElectricPumpRunning( ){} ... } public class PneumaticPumpDriver{ ... public void SwitchOn( ){...} }

Must be changed to incorporate new pumps

Delegate mechanism

The SwitchOnAllPumps method can use the delegate to call the appropriate method to turn on a pump without needing to determine the type of pump. A Delegate Allows a Method to Be Called Indirectly It contains a reference to a method All methods invoked by the same delegate must have the same parameters and return value A delegate is a similar to an interface. It specifies a contract between a caller and an implementer. A delegate associates a name with the specification of a method. No To use a delegate, body define it public delegate void StartPumpCallback( ); instantiate it. void Example(){ ElectricPumpDriver ed1 = new ElectricPumpDriver( ); StartPumpCallback callback; No callback =new StartPumpCallback(ed1.StartElectricPumpRunning); ... call callback(); call

} Method1(){}

DoWork(){ MethodX(); }
MethodX delegate

Method2(){}

Example
public delegate void StartPumpCallback( ); public class CoreTempMonitor2{ public void Add(StartPumpCallback callback){callbacks.Add(callback);} public void SwitchOnAllPumps( ){ foreach(StartPumpCallback callback in callbacks){ callback( ); } } private ArrayList callbacks = new ArrayList( ); } class ExampleOfUse{ public static void Main( ){ CoreTempMonitor2 ctm = new CoreTempMonitor2( ); ElectricPumpDriver ed1 = new ElectricPumpDriver( ); ctm.Add(new StartPumpCallback(ed1.StartElectricPumpRunning)); PneumaticPumpDriver pd1 = new PneumaticPumpDriver( ); ctm.Add(new StartPumpCallback(ed2.StartElectricPumpRunning)); ctm.SwitchOnAllPumps( ); } }

Events

Events allow an object to notify other objects that a change has occurred. The other objects can register an interest in an event, and they will be notified when the event occurs. How events work: Publisher: Raises an event to alert all interested objects (subscribers) Subscriber: Provides a method to be called when the event is raised Steps: Defining an Event: a publisher first defines a delegate and bases the event on it. public delegate void StartPumpCallback( ); private event StartPumpCallback CoreOverheating; Subscribing to an Event PneumaticPumpDriver pd1 = new PneumaticPumpDriver( ); ... CoreOverheating += new StartPumpCallback(pd1.SwitchOn); Notifying Subscribers to an Event
public void SwitchOnAllPumps( ) { if (CoreOverheating != null) CoreOverheating( ); }

Event: a new academic year (1/4)


public delegate void NewAcademicYearHandler( string s);
class University { Defining a delegate public void startNewAcademicYear() { NewAcademicYear("2008-2009"); FreshManParty("2008-2009"); } public event NewAcademicYearHandler NewAcademicYear; public event NewAcademicYearHandler FreshManParty; } class Teacher Subscriber: { provides method public Teacher(University u) { subscribes to an event univ = u; univ.NewAcademicYear+=new NewAcademicYearHandler(Syllabi); } private void Syllabi(string s) { Console.WriteLine("I am going to send the Syllabi for " +s+ " academic year"); } private University univ; }

Event: a new academic year (2/4)


class Student{ Subscribes to public Student(University u, bool miss) { many events univ = u; univ.NewAcademicYear+=new NewAcademicYearHandler(Enrolling); univ.FreshManParty+=new NewAcademicYearHandler(Participating); m=new NewAcademicYearHandler(MissContestEnrolling); if (miss) univ.FreshManParty += m; Can } unsubscribe public void unsubscribeMiss(){univ.FreshManParty -= m;} private void Enrolling(string s) { Console.WriteLine("I ask for enrolling in "+s+ " academic year"); } private void Participating(string s){ Console.WriteLine("I am going to participate to " + s + " FreshMan Party"); } private void MissContestEnrolling(string s){ Console.WriteLine("I am going to participate to " + s + " Miss Contest"); } private University univ; private NewAcademicYearHandler m; }

Event: a new academic year (3/4)


class Program { Applic ation static void Main(string[] args) { University upit = new University(); Student Andrei = new Student(upit, false), Sara=new Student(upit, true); Teacher Tudor = new Teacher(upit); Administrator NeaVasile = new Administrator(upit); upit.startNewAcademicYear(); //next year Console.WriteLine("No Miss Participation"); Sara.unsubscribeMiss(); upit.startNewAcademicYear(); } }

Event: a new academic year (4/4)


class Administrator{ Yet Another public Administrator(University u) { univ = u; subscriber univ.NewAcademicYear+=new NewAcademicYearHandler(Campus); } private void Campus(string s) { Console.WriteLine("The University Campus is ready for " +s+ " academic year"); } private University univ; }

Results?

Using a standard handler (for a predefined event)


using System; using System.Drawing; In System.EventHandler namespace: using System.Windows.Forms; public delegate void public class MainForm:Form{ EventHandler<TEventsArgs>(Object public static void Main(){ sender, TEventArgs e) MainForm f=new MainForm(); where TEventArgs:System.EventArgs Application.Run(f); } public MainForm(){ Text="Button Test"; Button b=new Button(); b.Location=new Point(this.Width/10,this.Width/10); b.Text="Try to click me!"; Controls.Add(b); // now you can see and press the button // but nothing happens! b.Click+= new EventHandler(bClicked); } private void bClicked(object sender, EventArgs e){ // note the use of paranthesis in ((Button)sender).Text expression if (((Button)sender).Text=="Try to click me!") { ((Button)sender).Text="Clicked!";

public delegate void PartyHandler(); public class Friend{ string week="MTWHFAS"; public void activity(){

Event PartyHandler, an example

foreach(char day in week){ if(day=='A')Party(); else work(); } } void work(){System.Console.WriteLine("I'm still working!");} public event PartyHandler Party; public static void Main(){ Friend f=new Friend(); InvitedForDrink invd= new InvitedForDrink(f); InvitedForFood invf= new InvitedForFood(f); f.activity(); invd.uninstall(); f.activity(); } } public class InvitedForFood{ private Friend friend; public InvitedForFood(Friend f){friend=f; friend.Party+= new PartyHandler(food); } void food(){System.Console.WriteLine("I should bring some food!");} } public class InvitedForDrink{ private Friend friend; PartyHandler ph; public InvitedForDrink(Friend f){

G:\C#\event2>f I'm still working! I'm still working! I'm still working! I'm still working! I'm still working! I should bring some drinks! I should bring some food! I'm still working! I'm still working! I'm still working! I'm still working! I'm still working! I'm still working! I should bring some food! I'm still working!

Installing an event

Note: drinks() and food() are inaccessible from outside!

Uninstalling an event

Indexers

Is a sort of property-like member with parameters. Enables a class to be accessed as if it were an array. A piece of code called an indexer accessor specifies what should be returned when the client uses the square brackets to access an element of the class.
indices are of any object type, including Indexer

public class Indexer{ public object this[int ind]{ get{ switch(ind){ case 0: return s0; case 1: return s1; default: return "Not a valid index"; } } set{ switch(ind){ case 0: s0=(string)value;break; case 1: s1=(int)value;break; } } } private string s0; private int s1; }

public class Appl{ public static void Main(){ Indexer i=new Indexer(); i[0]="Value for s0"; i[1]=1; System.Console.WriteLine( (string)i[0]+" "+i[1]); } }

Drawing with Graphic Device Interface +


public class Draw:Form{ [STAThread]public static void Main(){ Application.Run(new Draw()); } protected override void OnPaint(PaintEventArgs pp){ Graphics g=this.CreateGraphics(); Pen pr=new Pen(Color.Red,5); Pen pb=new Pen(Color.Blue,5); Bitmap img= new Bitmap(@"G:\C#\andreut.bmp"); g.DrawLine(pr,0,0,img.Width+20,0); // draw Ox- red g.DrawLine(pb,0,0,0,img.Width+20); // draw Oy- blue g.DrawImage(img,10,10); } }

Threading
Process: An executing instance of an application Thread: A path of execution within a process

Working with Resources


// compile with the option using System; using System.Drawing; using System.Windows.Forms; using System.Resources; using System.Reflection; public class MainForm:Form{ public static void Main(){ MainForm f=new MainForm(); Application.Run(f); } public MainForm(){ Text=Resources Test"; /res:string.resource

File string.txt; generate resources with: >resgen strig.txt to obtain string.resources #==================== # String Table #==================== # either #Message = Click Ok to see the window! # or Message = Apasa Ok pentru a vedea fereastra!

Click to edit the outline text format Second Outline Level Click to edit the Third Outline outline text format Level Second Outline Fourth Level Outline Third Outline Level

ResourceManager rm= new ResourceManager("string", Assembly.GetExecutingAssembly()); string msg= rm.GetString("Message"); MessageBox.Show(msg); // you see the MessageBox, but not the window } }

Display any message withput changing the source code Just change string.txt, generate new resources and recompile source code

XML documents parsing and validation


XML documents can reference optional documents that specify how the XML documents should be structured.
Document Type Definitions(DTDs)
DTDs use EBNF (Extended Backus-Naur Form) grammar to describe an XML documents content. XML parsers need additional functionality to read DTD, because it is not XML syntax. Schemas are XML documents that conform to a DTD, which define the structure of a Schema. These DTDs, which are bundled with the parser, are used to validate the Schemas that authors create Several types of schema exists: most popular

Schemas (preferred means of defining structures for XML documents in .NET)


Microsoft XML Schema W3C XML Schema W3C = World Wide Web Consortium

http://www.w3schools.com/XML/xml_validator.asp

Only Internet Explorer will actually check your XML against the DTD. Firefox, Mozilla, Netscape, and Opera will not.

XML document
well formed (i.e., it is syntactically correct, checked by parsers)

valid (i.e., conforms to the DTD or Schema, checked by validating parsers) used in business to business (B2B) transactions and mission-critical systems. many organizations and individuals are creating DTDs and Schemas repositories for a broad range of categories (e.g., financial transactions, medical prescriptions, etc.). Often, available free for download from the Web (i.e., http://opengis.net/) Microsofts msxml (nonvalidating parser,inside IE) C# programs can use msxml to validate XML documents against DTDs. For information on how to accomplish this, visit: msdn.microsoft.com/library/default.asp?url=/library/enus/cpguidnf/html/cpconvalidationagainstdtdwithxmlvalidatingreader.asp Microsofts XML Validator. (validating parser against DTDs) validate XML documents:
available free for download from msdn.microsoft.com/downloads/samples/Internet/xml/xml_validator/sample.asp) locally or by uploading the documents to the XML Validator Web site.

Valid XML documents:


Parsers: Various tools (many of which are free) parse or validate documents (visit www.w3.org)

Apache Software Foundations Xerces IBMs XML4J.

Reading and Validating XML Data with XmlReader


//http://go.microsoft.com/ pentru documentare The XmlReader class is an abstract base class that provides non-cached, forward-only, read-only access to XML data. It conforms to the W3C Extensible Markup Language (XML) 1.0 and the Namespaces in XML recommendations. The XmlReader class supports reading XML data from a stream or file. It defines methods and properties that allow you to move through the data and read the contents of a node. The current node refers to the node on which the reader is positioned. The reader is advanced using any of the read methods and properties return the value of the current node. The XmlReader class enables you to: Verify that the characters are legal XML characters, and that element and attribute names are valid XML names. Verify that the XML document is well formed. Validate the data against a DTD or schema. Retrieve data from the XML stream or skip unwanted records using a pull model. Although the Microsoft .NET Framework includes concrete implementations of the XmlReader class, such as the XmlTextReader, XmlNodeReader, and the XmlValidatingReader classes, in the 2.0 release the recommended practice is to create XmlReader instances using the Create method.

Validation Using a DTD with XmlReader


The XmlReader class can enforce validation using a DTD or Schema definition language (XSD) schema. The ValidationType property on the XmlReaderSettings class determine whether the XmlReader instance enforces validation.

To perform validation against a DTD, the XmlReader uses the DTD defined in the DOCTYPE declaration of an XML document. The DOCTYPE declaration can either point to an inline DTD or can be a reference to an external DTD file.

Set the XmlReaderSettings.ProhibitDtd property to false. Set the XmlReaderSettings.ValidationType property to ValidationType.DTD. If the DTD is an external file stored on a network resource that requires authentication, pass an XmlResolver object with the necessary credentials to the Create method.

Example: validate an XML file using a DTD file.


d:\tudor\csharp\xml\letter.xml
<!-- Deitel--> <!-- Fig. 18.12 Document Type Definition (DTD) for a business letter--> <!-- <!ELEMENT letter ( contact+, salutation, paragraph+,closing, signature )> <!ELEMENT contact ( name, address1, address2, city, state,zip, phone, flag )> <!ATTLIST contact type CDATA #IMPLIED> <!ELEMENT name ( #PCDATA )> <!ELEMENT address1 ( #PCDATA )> <!ELEMENT address2 ( #PCDATA )> <!ELEMENT city ( #PCDATA )> <!ELEMENT state ( #PCDATA )> <!ELEMENT zip ( #PCDATA )> <!ELEMENT phone ( #PCDATA )> <!ELEMENT flag EMPTY> <!ATTLIST flag gender (M | F) "M"> <!ELEMENT salutation ( #PCDATA )> <!ELEMENT closing ( #PCDATA )> <!ELEMENT paragraph ( #PCDATA )> <!ELEMENT signature ( #PCDATA )>

<?xml version = "1.0"?> <!-- Deitel --> <!-- Fig. 18.13: letter2.xml --> <!-- Business letter formatted with XML --> <!DOCTYPE letter SYSTEM "d:\tudor\csharp\xml\letter.dtd"> <letter> <contact type = "from"> <name>Jane Doe</name> <address1>Box 12345</address1> <address2>15 Any Ave.</address2> <city>Othertown</city> <state>Otherstate</state> <zip>67890</zip> <phone>555-4321</phone> <flag gender = "F" /> </contact> <contact type = "to"> <name>John Doe</name> <address1>123 Main St.</address1> <address2></address2> <city>Anytown</city> <state>Anystate</state> <zip>12345</zip> <phone>555-1234</phone> <flag gender = "M" /> </contact>

Validation using Schemas


Microsoft XML Schema (obsolete) W3C XML Schema


W3C = World Wide Web Consortium C#: XmlReader si XmlSchemaSet

XmlReader provides forward-only, read-only access to a stream of XML data. The XmlReader class conforms to the W3C Extensible Markup Language (XML) 1.0 and the Namespaces in XML recommendations.

The current node refers to the node on which the reader is positioned. The reader is advanced using any of the read methods and properties reflect the value of the current node. Important Note: Although the Microsoft .NET Framework includes concrete implementations of the XmlReader class, such as the XmlTextReader, XmlNodeReader, and the XmlValidatingReader classes, in the 2.0 release the recommended practice is to create XmlReader instances using the Create method. For more information, see Creating XML Readers.

In System.Xml version 1.0, XML schemas were loaded into an XmlSchemaCollection class as a library of schemas. In System.Xml version 2.0, the XmlValidatingReader and the XmlSchemaCollection classes are obsolete, and have been replaced by the Create method and the XmlSchemaSet class, respectively.

The XmlSchemaSet has been introduced to fix a number of issues, including standards compatibility, performance, and the obsolete Microsoft XML-Data Reduced (XDR) schema format.

Only supports W3C XML schemas.

The following is a comparison between the XmlSchemaCollection class and the XmlSchemaSet class. In System.Xml version 1.0, XML schemas were loaded into an XmlSchemaCollection class as a library of schemas. In System.Xml version 2.0, the XmlValidatingReader and the XmlSchemaCollection classes are obsolete, and have been replaced by the Create method and the XmlSchemaSet class, respectively.

http://msdn2.microsoft.com/en-us/library/

Validation XmlSchemaSet
<?xml version = "1.0"?> <!-- Fig. 18.18: bookxsd.xml --> <!-- Document that conforms to W3C XML Schema -->

Deitelbooks.xml

<deitel:books xmlns:deitel = "http://www.deitel.com/booklist"> <book> <title>e-Business and e-Commerce How to Program</title> </book> <bok> <title>Python How to Program</title> </bok> </deitel:books>
<?xml version = "1.0"?> <!-- Fig. 18.19: book.xsd --> <!-- Simple W3C XML Schema document -->

Deitelbooks.xsd

<xsd:schema xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:deitel = "http://www.deitel.com/booklist" targetNamespace = "http://www.deitel.com/booklist"> <xsd:element name = "books" type = "deitel:BooksType"/> <xsd:complexType name = "BooksType"> <xsd:sequence> <xsd:element name = "book" type = "deitel:BookType" minOccurs = "1" maxOccurs = "unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name = "BookType"> <xsd:sequence> <xsd:element name = "title" type = "xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema>

Validation XmlSchemaSet
<?xml version = "1.0"?> <carti:carti xmlns:carti= "spatiuDeNume"> carti.xml <cartea> <titlu>e-Business and e-Commerce How to Program</titlu> </cartea> <carte> Invalid child <titlu>Python How to Program</titlu> </carte> </carti:carti> carti:here, namespace <?xml version = "1.0"?> <xsd:schema xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:carti = "spatiuDeNume" targetNamespace = "spatiuDeNume"> <xsd:element name = "carti" type = "carti:BooksType"/> <xsd:complexType name = "BooksType"> <xsd:sequence> <xsd:element name = "carte" type = "carti:BookType" minOccurs = "1" maxOccurs = "unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name = "BookType"> <xsd:sequence> <xsd:element name = "titlu" type = "xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> Cart: here, Root element from spatiuDeNume

carti.xsd

XmlReader DTD/Schema Validating program


using System.Xml; using System.Xml.Schema; using System.IO; public class Sample { public static void Main(string[] args) { // Set the validation settings. XmlReaderSettings settings = new XmlReaderSettings(); if(args[1]=="DTD"){ // validating against a DTD settings.ProhibitDtd = false; settings.ValidationType = ValidationType.DTD; }else{ // validating against a schema

> D:\Tudor\Csharp\XML\Validate\XMLReader\XMLReader.exe letter DTD letter.xml, in D:\Tudor\Csharp\XML\ Valid xml text, according with the specified DTD

>D:\Tudor\Csharp\XML\Validate\XMLReader>XmlReader nonvalidletter DTD


Validation Error: The element 'letter' has invalid child element 'adresa'. List of possible elements expected: 'contact salutation'. Validation Error: The 'adresa' element is not declared. targetNamespace of the schema

>D:\Tudor\Csharp\XML\Validate\XMLReader>XmlReader deitelbooks Schema settings.ValidationType = ValidationType.Schema; Validation Error: The element 'books' in namespace 'http://www.deitel.com/booklist' has invalid child settings.Schemas.Add("http://www.deitel.com/booklist", "Schemas//deitelbooks.xsd"); element 'bok'. List of possible elements expected: 'book'. // the value of Schemas settings.Schemas.Add("spatiuDeNume", "Schemas//carti.xsd"); property is an XmlSchemaSet D:\Tudor\Csharp\XML\Validate\XMLReader>XmlReader carti Schema object // the value of Schemas property is an XmlSchemaSet objectin namespace 'spatiuDeNume' has invalid child element 'cartea'. List Validation Error: The element 'carti' of possible elements expected: 'carte'.
} checked against: deitelbooks.xsd or carti.xsd settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); // Create the XmlReader object. XmlReader reader = XmlReader.Create("d:\\tudor\\csharp\\xml\\"+args[0]+".xml", settings); // Parse the file. while (reader.Read());

Transforming and Formatting XML data

Tutorials: http://www.topxml.com/xsl/articles/xsl_transformations/

Extensible Stylesheet Language (XSL) http://www.w3schools.com/xsl/xsl_templates.asp XSL has two parts XSLT 2.0 a transformation language (XSLT), and http://www.w3.org/TR/xslt20/ a formatting language. often transform a document before formatting it XSLT: creates formatted text documents from XML documents
One of the most common transformations is from XML documents to HTML documents

To create an XSLT transformation, you need two well-formed XML documents:


the document to transform, the style sheet that specifies the transformation.

Transformations involves two tree structures: Source tree (XML document) Result tree (i.e., any text-based format such as XHTML) Transformation by XSLT processors, such as Microsofts msxml Just load sorting.xml by InternetExplore Apache Software Foundations Xalan

Style Sheet document

Style Sheet document (*.xsl)


Declaration Since an XSL style sheet is an XML document itself, it always begins with the XML declaration: <?xml version="1.0" encoding="ISO-8859-1"?>. The root element that declares the document to be an XSL style sheet is <xsl:stylesheet> or <xsl:transform> (completely synonymous) <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> or: <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> To get access to the XSLT elements, attributes and features: declare the XSLT namespace at the top of the document.

xmlns:xsl="http://www.w3.org/1999/XSL/Transform" (the official W3C XSLT namespace. If you use this namespace, you must also include the attribute version="1.0).

Content An XSL style sheet consists of one or more set of rules that are called templates.

Each template contains rules to apply when a specified node is matched.

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <! content of the template element here </xsl:template> </xsl:stylesheet> When the root node is matched, the template is applied to that node. The XSL processor replaces the node with the content of the rule

match attribute,set to match the root

XSL templates

<xsl:choose>

<xsl:template match= XPath_exp > element used to build templates. the match attribute is used to associate a template with an XML element. the value of the match attribute is an XPath expression i.e. match="/" defines the whole XML document. <xsl:apply-templates> element apply templates to the children of a node that you've matched <xsl:value-of select= XPath_exp > element gets the value of selected nodes XPath expression works like navigating a file system; <xsl:value-of select="catalog/cd/title"/> where a forward slash (/) selects subdirectories. <xsl:sort select="artist"/> </xsl:value-of> <xsl for-each select= XPath_exp > element Filter the output from XML file Legal filter operators are: select every XML element of a specified node-set: = , !=, &lt, &gt <xsl:for-each select="catalog/cd[artist='Bob Dylan']"> <xsl:sort> element sort the output, add <xsl:sort> element inside the <xsl:for-each> element <xsl:if> element put a conditional if test against the content of the XML file <xsl:for-each select="catalog/cd"> <xsl:if test="price &gt; 10"> <xsl:choose>, <xsl:when>, and <xsl:otherwise> insert a multiple conditional test against the XML file,
<xsl:when test="price &gt; 10"> </xsl:when> <xsl:when test="price &gt; 9"> </xsl:when>

XSLT document processed by Internet Explorer


<?xml version = "1.0"?> <!-- Fig. 18.23: sorting.xml --> <!Load sorting.xml in IE--> <!-- XML document containing book information --> <?xml:stylesheet type = "text/xsl" href = "sorting.xsl"?> <book isbn = "999-99999-9-X"> <title>Deitel&apos;s XML Primer</title> <author> <firstName>Paul</firstName> <lastName>Deitel</lastName> </author> <chapters> <frontMatter> <preface pages = "2" /> <contents pages = "5" /> <illustrations pages = "4" /> </frontMatter> <chapter number = "3" pages = "44"> Advanced XML</chapter> <chapter number = "2" pages = "35"> Intermediate XML</chapter> <appendix number = "B" pages = "26"> Parsers and Tools</appendix> <appendix number = "A" pages = "7"> Entities</appendix> <chapter number = "1" pages = "28"> XML Fundamentals</chapter> </chapters> <media type = "CD" /> </book>

Deitel's XML Primer


by Deitel, Paul

preface ( 2 pages ) contents ( 5 pages ) illustrations ( 4 pages ) Chapter 1 ( 28 pages ) Chapter 2 ( 35 pages ) Chapter 3 ( 44 pages ) Appendix A ( 7 pages ) Appendix B ( 26 pages ) Pages: 151 Media Type: CD

The XSL document, that transforms sorting.xml to XHTML.


<?xml version = "1.0"?> <!-- Fig. 18.24: sorting.xsl --> <!-- Transformation of book information into XHTML --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"> <!-- write XML declaration and DOCTYPE DTD information --> <xsl:output method = "xml" omit-xml-declaration = "no" doctype-system = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" doctype-public = "-//W3C//DTD XHTML 1.0 Strict//EN"/> <!-- match document root --> <xsl:template match = "/"> <html xmlns = "http://www.w3.org/1999/xhtml"> <xsl:apply-templates/> </html> </xsl:template> <!-- match book --> <xsl:template match = "book"> <head> <title>ISBN <xsl:value-of select = "@isbn" /> <xsl:value-of select = "title" /></title> </head> <body> <h1 style = "color: blue"> <xsl:value-of select = "title"/></h1> <h2 style = "color: blue">by <xsl:value-of select = "author/lastName" />, <xsl:value-of select = "author/firstName" /></h2>

<td> ( <xsl:value-of select = "@pages" /> pages ) </td> </tr> </xsl:for-each> <xsl:for-each select = "chapters/chapter"> <xsl:sort select = "@number" data-type = "number" order = "ascending" /> <tr> <td style = "text-align: right"> Chapter <xsl:value-of select = "@number" /> </td> <td> ( <xsl:value-of select = "@pages" /> pages ) </td> </tr> </xsl:for-each> <xsl:for-each select = "chapters/appendix"> <xsl:sort select = "@number" data-type = "text" order = "ascending" /> <tr> <td style = "text-align: right"> Appendix <xsl:value-of select = "@number" /> </td> <td> ( <xsl:value-of select = "@pages" /> pages ) </td> </tr> </xsl:for-each> </table>

<br /><p style = "color: blue">Pages: <xsl:variable name = "pagecount" select = "sum(chapters//*/@pages)" /> <xsl:value-of select = "$pagecount" /> <br />Media Type: <xsl:value-of select = "media/@type" /></p> </body> </xsl:template> </xsl:stylesheet>

C# programatically transformation 1/4


// Fig. 18.25: XslCompiledTransform.cs Use:>transformtest // Applying a style sheet to an XML document. using System; using System.Windows.Forms; using System.Xml; using System.Xml.XPath; // contains XPath classes using System.Xml.Xsl; // contains style sheet classes using System.IO; // contains stream classes // transforms XML document to XHTML public class TransformTest : System.Windows.Forms.Form{ private System.Windows.Forms.TextBox outputTextBox; private System.Windows.Forms.Button transformButton; //private System.ComponentModel.Container components = null; private XmlDocument document; // Xml document root private XPathNavigator navigator; // navigate document private XslCompiledTransform transformer; // transform document private StringWriter output; // display document private string filesName;// name of .xml, .xsl and .html files public TransformTest(string[] args){ filesName=args[0]; InitializeComponent(); // load XML data document = new XmlDocument(); //document.Load( "..\\..\\args[0]"+".xml" ); document.Load( filesName+".xml" ); // create navigator navigator = document.CreateNavigator(); // load style sheet transformer = new XslCompiledTransform(); transformer.Load( filesName+".xsl" ); } // end constructor

<nume fisier xml fara extensie>

C# programatically transformation 2/4 Transform method


// Windows Form Designer generated code [STAThread] static void Main(string[] args){ Application.Run( new TransformTest(args) ); } // end Main // transformButton click event private void transformButton_Click( object sender,System.EventArgs e ){ // transform XML data output = new StringWriter(); transformer.Transform( filesName+".xml",filesName+".html" ); transformer.Transform(navigator,null,output); // display transformation in text box outputTextBox.Text = output.ToString(); // close streams output.Close(); } // end transformButton_Click

Click EventHandler

C# programatically transformation 3/4 InitializeComponent


private void InitializeComponent(){ this.Name = "XSL Transformation"; this.Text = "Transformation Test"; this.Size = new System.Drawing.Size(800, 500); // Create an instance of a TextBox control. outputTextBox = new TextBox();

// Set the Multiline property to true. outputTextBox.Multiline = true; // Add vertical scroll bars to the TextBox control. outputTextBox.ScrollBars = ScrollBars.Vertical; // Allow the RETURN key in the TextBox control. outputTextBox.AcceptsReturn = true; // Allow the TAB key to be entered in the TextBox control. outputTextBox.AcceptsTab = true; // Set WordWrap to true to allow text to wrap to the next line. outputTextBox.WordWrap = true; // Set the default text of the control. outputTextBox.Text = "Welcome!"; this.outputTextBox.Location = new System.Drawing.Point(16, 16); this.outputTextBox.Name = "outputTextBox"; this.outputTextBox.Size = new System.Drawing.Size(300, 200); this.outputTextBox.TabIndex = 0; this.outputTextBox.Text = "outputTextBox"; Controls.Add(outputTextBox); transformButton=new Button(); transformButton.Location = new System.Drawing.Point(350, 20); transformButton.Text="transform"; transformButton.Click +=new System.EventHandler(transformButton_Click); Controls.Add(transformButton); } // end method InitializeComponent } // end Transformation

C# programatically transformation 4/4 xml and xsl files


XML file, the source <?xml version="1.0" encoding="ISO-8859-1"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <year>1985</year> </cd> <cd> <title>On the Night</title> <artist>Dire Straits</artist> <country>USA</country> <company>Universal Music</company> <price>50.90</price> <year>2004</year> </cd> </catalog>

XSL file <?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/"> <html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> </tr> <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template></xsl:stylesheet>

My CD Collection
XHTML file <html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> </tr> <tr> <td>Empire Burlesque</td> <td>Bob Dylan</td> </tr> <tr> <td>On the Night</td> <td>Dire Straits</td> </tr> </table> </body> </html>

Title On the Night

Artist Dire Straits

Empire Burlesque Bob Dylan

Data Base programming


History of standard ways to access databases programatically
1. ODBC: Open Data Base Connectivity, oriented to C and difficult to use in other languages, like VB 2. ADO (Active Data Objects): a data access technology designed for use with any language that supports Microsofts Common Object Model (COM); Disconnected recordsets facilitate distributed applications OLE DB program OLE DB, the low level API behind ADO

ODBC API program

ODBC driver

MS OLEDB provider for ODBC

OLE DB provider

Native DB

Native DB

3. ADO.NET: improves on the concept of disconnected recordset introducing DataSet (an abstraction of data base); a DataSet contains one or more DataTable; a DataTable has DataColumn, DataRow, DataRelation etc.
ADO.NET has two sets of similar classes: Generic classes, to access all DB that have OLE DB providers (prefixed by OleDb or Ado in beta 1 release ); portability SQL-server specific classes (prefixed by Sql); efficiency

ADO.NET Example: Connection for Microsoft Accesss


using System; using System.Data; using System.Data.OleDb; class DB{ public static void Main(){ OleDbConnection oledbconn= new OleDbConnection( @"Provider=Microsoft.Jet.OleDb.4.0; Data Source=g:\C#\OLEDB\db1.mdb"); OleDbCommand cmd=new OleDbCommand( "SELECT * FROM table1 ORDER BY first",oledbconn); OleDbDataReader outData=null; cmd.CommandType=CommandType.Text; try{ oledbconn.Open();

Click to edit the outData=cmd.ExecuteReader(); outline text format while(outData.Read()){


}

Console.WriteLine("first: {0} last:{1} \n", outData["first"], outData["last"]);

Second Outline } Level catch(Exception e){

Console.WriteLine("Exception: {0}",e.Message);} finally {oledbconn.Close();}

} }

Database db1.mdb Table1: first last Tudor Balanescu Andrei Burlacu

Third Outline Level Fourth Results: first: Andrei last:Burlacu Outline Level first: Tudor last:Balanescu Fifth Outline

Bibliografie
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Ben Albahari: A Comparative Overview of C# Deitel: C# How to Program Charles Petzold: Programare in Windows cu C#, Teora, 2003 Jeff Ferguson, Brian Patterson, Jason Beres,Pierre Boutquin, and Meeta Gupta: C# Bible, Wiley Publishing Inc., 2002 Larry OBrien, Bruce Eckel: Thinking in C#, Prentice Hall,2002 Richter, Jeffrey: CLR via C#, Microsoft Press, 2006, second edition http://www.topxml.com/xsl/articles/xsl_transformations/ http://www.w3schools.com/xsl/xsl_templates.asp http://www.w3.org/TR/xslt20/ C# MSDN Training

You might also like