C
C
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
C++
Modula
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.
NET Compact
Mobile devices
Portability Efficiency
(bad) (good)
Java program Java compiler C# program C# compiler (csc)
VB program VB compiler
Another machine
Java machine- free intermediate code (byte code) Java virtual machine for A
Another machine
JIT compiler for A (first run) (volatile)Code for machine A Runtime environment machine A (subsequent runs) results
Another machine
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
(1/2)
/// 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
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
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
Console app.
(System. Console)
Windows app
(System.Windows)
MS-DOS prompt does not return until program terminates -the results remain displayed
debug mode: MSDOS prompt return immediately, before program terminates release mode: Press any key
Errors
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.
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)
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(); } }
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.
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
Compiling process
- 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
- 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)
/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.
Jeffrey Richter, ch 1.
indicates the type of file: GUI, CUI, or DLL, contains a timestamp indicating when the file was built.
(C#, Visual Basic, JScript, J# (a Java language compiler), IntermediateLanguage Assembler (ILAsm.exe), etc. )
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.
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
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.
Combining modules
Combining by compiling
Combining by linking
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.
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).
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
Application Deployment
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: 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
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>
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):
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.
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.
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).
1: Key pair (public, private) written to Public key written to There is no way to display the private key
>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)
Repeating 1; and 2; to create an updated version of stringer.dll, >client (and no compilation of client) Does not work
Signing an assembly
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.
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 .
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
>client
>gacutil /u stringer >client Instead of gacutil, you can use drag and drop to install! System.IO.FileNot FoundException:
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.
<?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
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:
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: 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 (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.
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
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
alias using directive for a namespace alias using directive for a type
Error: an ambiguous reference to B.L1.C and A.L2.C
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.
//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
//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 } } }
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
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.
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.
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.
1. 2. 3.
1.
Type visibility:
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.
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())
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;
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
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)
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
class
private
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(); } }
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
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."); } } }
//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
Compile with: >csc /t:module NS1mod2.cs >csc /t:module NS1mod3.cs Link with:
>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
(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
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.
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!
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
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
marshaling by value
There are non marshalable types. // ---not [Serializable]---public class MarshalByValType : System.Object {}
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
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
SomeMethod()
mbrt.SomeMethod(
Real and Copy: separate lifetimes, and their states can change independently of each other
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
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.
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
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 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.
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
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.
(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();} }
(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>();
(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
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
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();
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.
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
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()
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
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.
base type:
System.ValueType for struct System.Enum for enum
base type:
System.Object
Simple types are identified by means of reserved keywords. These reserved keywords are aliases for predefined structure types.
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(); } } }
Multi dimensional
jagged
(like in Java)
j2=new int[2][];
rectangular (not in Java, could be more performant) int[,] a2; // true rectangular
int[,,] a3; // true parallelipiped
True
Click to edit the j2=new int[2][]; outline text format 11 12 j2[0]=new int[] {11,12,13};
13
a2
23
11 21
12 22
13 23
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};
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};
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!).
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:
Initializer list Only in constructors public void Init():this(0,0){} No recursion public C(int x):this(0){}
public Date( ) : this(1970, 1, 1){} public Date(int year, int month, int day){ ccyy = year; mm = month; dd = day; }
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;
Implicitly to zero, false or null Explicitly at their declaration in a variable initializer Explicitly inside an instance constructor
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.
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).
no initialization of struct fields, so any field must be definitely assigned before it can be referenced
Initialization, OK
// 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; } }
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.
true!
Static Constructors
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
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 .
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
Resource which is part of an assembly. native .Net objects, (arrays etc.) Unmanaged heap memory blocks (native resource),
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
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.
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
count
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
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
>csc /debug TimerCallback method is called just once! garbage collection reclaims the memory for
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[+/-]
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
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
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)
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
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();
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
Example: Dispose
(see)
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(); }
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 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"); // }
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
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 }
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)
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).
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.
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()
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);
Third Outline Level Fourth Outline FragileExtension displays 3 and 6 etc. Level
b.callMultipleTimes(3); b.callMultipleTimes(3); System.out.println(b.counter);
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. } } }
>csc /t:library Phone1000.csc And see its metadata with >ildasm Phone1000.dll
>csc /t:library /r:Pone1000.dll BetterPhone1000.csc And see its metadata with >ildasm BetterPhone1000.dll
>csc /t:exe /r:Pone1000.dll,BetterPhone1000.dll app.csc And see its metadata with >ildasm app.exe Run with >app.exe
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. } } }
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
Abstract classes
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); } }
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
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 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; }
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);} ... }
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.
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( ){...} }
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( ); }
Results?
public delegate void PartyHandler(); public class Friend{ string week="MTWHFAS"; public void activity(){
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
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]); } }
Threading
Process: An executing instance of an application Thread: A path of execution within a process
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
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.
Parsers: Various tools (many of which are free) parse or validate documents (visit www.w3.org)
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.
<?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>
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.
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
> 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
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());
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
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
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.
<?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
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: = , !=, <, > <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 > 10"> <xsl:choose>, <xsl:when>, and <xsl:otherwise> insert a multiple conditional test against the XML file,
<xsl:when test="price > 10"> </xsl:when> <xsl:when test="price > 9"> </xsl:when>
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
<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>
Click EventHandler
// 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
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>
ODBC driver
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
} }
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