c#/.net programmingats/cs-2004-1/pdf/skript.pdf · anders hejlsberg (turbo pascal, delphi)....

97
C#/.NET Programming Axel-Tobias Schreiner Department of Computer Science Rochester Institute of Technology Objectives Completely cover the language C#. Cover the new developments in .NET 2005 beta (Whidbey). Look at some design patterns. Introduce at least some .NET services. Demonstrate language interoperation.

Upload: buixuyen

Post on 26-Sep-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

C#/.NET Programming

Axel-Tobias Schreiner

Department of Computer Science

Rochester Institute of Technology

Objectives

Completely cover the language C#.

Cover the new developments in .NET 2005 beta (Whidbey).

Look at some design patterns.

Introduce at least some .NET services.

Demonstrate language interoperation.

References

Books on object-oriented programming in general:

Visual Studio contains tons of useful help, including a language definition.

C#

Anders Hejlsberg (Turbo Pascal, Delphi).

Features from C++ and Java.

Simple inheritance, garbage collection.

Value types, boxing.

Pointers in

unsafe

code.

Operator (but no cast) overloading.

New: generics (list of string, etc.), lambdas.

Albahari et al. 0-596-00315-3 C# Essentials (2nd ed.)Albahari et al. 0-596-00526-1 C# in a Nutshell (2nd ed.)Gunnerson 1-893115-62-3 A Programmer’s Introduction

to C# (2nd ed.)Hejlsberg et al. 0-321-15491-6 The C# Programming Lan-

guageLiberty 0-596-00489-3 Programming C# (3rd ed.)

Budd 0-201-76031-2 An Introduction to Object-Ori-ented Programming (3rd ed.)

Cooper 0-201-84453-2 C# Design PatternsGamma et al. 0-201-63361-2 Design Patterns

.NET Framework

Common Language Runtime (CLR).

Common Type System (CTS).

Common Language Specification (CLS).

Intermediate Language (MSIL).

Just-in-time compilation.

Framework Class Library (FCL).

Reflection.

Security.

Generics, etc. are in .NET 2005 (version 1.2 and 2.0).

First Steps

Walkthrough to get a working environment.

Installation

For version 1 command line tools, install the Shared Source Common Language Infrastructure (SSCLI) for MacOS X or FreeBsd or install the .NET Framework Software Development Kit on Windows (NT, 2K, or XP).

For version 2 visit the Visual Studio 2005 Beta homepage and download the Express editions for C++, C#, J#, and Web Devel-oper (about 400 MB).

Alternatively, if you study computer science at RIT, contact Sam Waters for access to the complete product (5 CDs or more).

Command Line Tools

Sufficient if separate compilation and reuse is not an issue.

A build tool such as

nmake

is convenient. Version 2 includes

msbuild

(similar to ant); however, automating program testing would require some work.

nmake

and a properly configured command line window are part of the Express edition of C++; to download visit the Visual Stu-dio 2005 Beta homepage. Alternatively, you could download an older version of nmake.

Hello, World!

Use any plain text editor and create Hello.cs

using System;class Hello { static void Main () { Console.WriteLine("Hello, World!"); }}

Unix

For Unix and a Bourne shell, create setup.sh

SSCLI=/usr/local/sscli # root of SSCLI

if [ -z "$ROTOR_DIR" ]; then d="`pwd`" cd "$SSCLI" && . env.sh cd $dfi

Compile and execute as follows:

$

. setup.sh

Fastchecked Environment$

csc /nologo Hello.cs

$

clix Hello.exe

Hello, World!

Windows

For Windows, run

Command Prompt

from the

Visual Studio/Tools

menu.

Compile and execute as follows:

>

csc /nologo Hello.cs

>

Hello

Hello, World!

Security

If

Hello.exe

resides on a networked volume, you may not be allowed to execute it.

Try to execute

mscorcfg.msc

and

Add Child Code Group

for the

Internet

zone with

Execution

or even

Full Trust

permis-sion.

Be sure to remove this before you quit — it is a security hole!

Alternatively, copy

Hello.exe

to a local disk and execute from there.

Visual Studio

Preferable, if initially overwhelming.

Visual C# Express

is simplified and supports a single language.

Editor.

Context Help.

File and Build Management.

Debugger.

Project

In

File/New/Project

select Console Application and fill in the project name

Test

(not the class name):

•••

Once you select

File/Save All

or close the project, you can select under which name and where it is saved:

Edit

Type text in the

View

/

Code

window.

Manage file names by selecting, overtyping and/or deleting in

View

/

Solution

Explorer

.

Arrange indentation in

Tools/Options/Text Editor

.

•••

Alternatively, delete a file name in

Solution Explorer

and

Add Existing Item

to import Hello.cs.

Build

Select

Build

/Build Solution or Rebuild Solution:

Execute

Select Debug/Start and look at Debug/Windows/Console:

Alternatively click on the code window frame to set a breakpoint and select Debug/Start.

Deploy

Once the solution is built and saved, the executable file isTest\Test\bin\Release\Test.exe

i.e.,solution\project\bin\Release\project.exe.

Object-Oriented Program-mingConvert temperatures between Celsius and Fahrenheit.

Designing, making, and (re-)using classes.

Language interoperation.

Conventional programDegF reads numbers from the command line and converts them from degrees Celsius to Fahrenheit:using Console = System.Console;namespace Edu.Rit.CS.ATS.Conversions { class DegF { static int Main (string[] args) { if (args != null) for (int a = 0; a < args.Length; ++ a) { double celsius = double.Parse(args[a]); Console.WriteLine("\t"+ (9*celsius / 5 + 32)); } return 0; } }}

Language

Documentation

DegF contains XML-based documentation comments:/// <summary>/// takes degrees Celsius from the command line,/// prints degrees Fahrenheit./// </summary>

csc has an option /doc to collect the documentation in an XML file.

nDoc uses this file, the assemblies, and the MS Help Workshop to produce MSDN-Library-style documentation.

Other documentation styles are planned but there is little progress.

At this point this only works for the framework versions 1.0 and 1.1.

using x = namespace.y; imports and (re-)names an accessi-ble type.

using namespace; imports all accessible types, simpli-fies referencing.

namespace path { } qualifies names.internal class name { } internal to assembly by default.private ... private to class by default.array.Length number of all elements.double.Parse(string) double is a class.string + something concatenation with ToString().

Execution

Command line arguments for debugging can be specified in the Properties/Debug panel for the project:

Object-oriented designDegF sends the numbers to a converter and displays the result.

IConversion describes conversion.

LinearConversion implements a x + b.

Main programusing Console = System.Console;namespace Edu.Rit.CS.ATS.Conversions { public class DegF { protected static IConversion conversion = new LinearConversion(9.0/5, 32.0); public static int Main (string[] args) { if (args != null) for (int a = 0; a < args.GetLength(0); ++ a) { double x = double.Parse(args[a]); Console.WriteLine("\t"+ conversion.Y(x)); } return 0; } }}

•••

Interface

Collection of public method headers, promises behaviour.

Multiple inheritance (no data fields).namespace Edu.Rit.CS.ATS.Conversions { public interface IConversion { double Y (double x); // public, virtual, abstract }}

protected class and subclasses.protected internal class, subclasses, and assembly.static field common to class.static name () { .. } constructor for class initialization.9.ToString() literals are objects.public visible everywhere.int array[2][] array of arrays.int array[2,3] multidimensional array.array.GetLength(dim) elements along a dimension.

•••

Implementationnamespace Edu.Rit.CS.ATS.Conversions { public class LinearConversion: IConversion { readonly double _a, _b; public double a { get { return _a; }} public double b { get { return _b; }} public LinearConversion (double a, double b) { _a = a; _b = b; } public double Y (double x) { return a*x + b; } }}

interface promises methods.abstract class can have abstract methods; method must be

overridden, implicitly virtual.virtual method is dynamically bound, can be overridden.override virtual method is overridden.new virtual method is not overridden.

•••

Compilation

One assembly:> csc /nologo DegF.cs IConversion.cs LinearConversion.cs

Several assemblies:> csc /nologo /t:library IConversion.cs> csc /nologo /t:library /r:IConversion.dll LinearConversion.cs> csc /nologo /out:DegF.exe /r:IConversion.dll;LinearConversion.dll DegF.cs

InheritanceDegC inherits from DegF to send the numbers to a converter and display the result.

IReversibleConversion describes inverting a conversion.

ReversibleLinearConversion implements inverting a x + b.

Implemented in J#.

class name: base, interfaces { } inheritance.readonly runtime, must be initial-

ized.const compile time, static.property field with get and set

methods.

Interfacepackage Edu.Rit.CS.ATS.Conversions;public interface IReversibleConversion extends IConversion { IConversion inverse (); // public}

Implementationpackage Edu.Rit.CS.ATS.Conversions;public class ReversibleLinearConversion extends LinearConversion implements IReversibleConversion { public ReversibleLinearConversion(double a,double b) { super(a, b); } public IConversion inverse () { return new LinearConversion(1/get_a(), - get_b()/get_a()); }}

Property a is inherited as get_a and set_a methods.

Main programpackage Edu.Rit.CS.ATS.Conversions;public class DegC extends DegF { static { conversion = new ReversibleLinearConversion(9./5, 32.).inverse(); } public static void main (String[] args) { DegF.Main(args); }}

main() needs to be implemented within the assembly.

Compilation

Import referenced assemblies:> copy ..\oop\*.dll .> copy ..\oop\*.exe .

One additional assembly:> vjc /nologo /out:DegC.exe /r:DegF.exe;IConversion.dll;LinearConversion.dll DegC.jsl IReversibleConversion.jsl ReversibleLinearConversion.jsl

References can be located on a search path.

At runtime, private assemblies are found in the executable direc-tory (and it’s subdirectories if configured).

AssembliesAssembly: collection of files, contains manifest, appears as one executable (.exe) or dynamic link library (.dll).

Assembly is loaded as needed.

Module: one file, no manifest.

ildasm to analyze.

Visual StudioOne project is compiled into one assembly.

Project must reference necessary assemblies from other projects or solutions, implicitly copied into bin directory for deployment.

Right-click Solutions Explorer/References. Then Browse to assembly.

Note that assembly is copied, not linked to.

Command LineCompiler creates module (/t:module) or assembly (/t:exe or /t:library).

Compiler can reference assembly (/r:x.exe;y.dll) or (C# only) module (/addmodule:z.netmodule).

Each creates a link to an external file; /addmodule influences scope.

Assembly Linker al creates assembly as manifest for modules, i.e., it can create a multi-file assembly. The modules are loaded as needed.

Compilation

One assembly:> csc DegF.cs IConversion.cs LinearConversion.cs

Several assemblies:> csc /t:library IConversion.cs> csc /t:library /r:IConversion.dll LinearConversion.cs> csc /r:IConversion.dll;LinearConversion.dll DegF.cs

•••

One assembly, many files:> csc /t:module IConversion.cs> csc /t:module /addmodule:IConversion.netmodule LinearConversion.cs> csc /t:module /addmodule:LinearConversion.netmodule /addmodule:IConversion.netmodule DegF.cs> al /t:exe /out:DegF.exe /main:Edu.Rit.CS.ATS.Conversions.DegF.Main DegF.netmodule IConversion.netmodule LinearConversion.netmodule

DeploymentReferenced assemblies are found

— in the same directory as the startup assembly

— in the global assembly cache (with strong names)

— in a subdirectory such as name/name.dll

— in a subdirectory mentioned in a configuration file

Configuration Files

name.exe can be configured in name.exe.config.

Tons of options, see SDK documentation.

probing gives hints in what subdirectories assemblies might be:<configuration> <runtime> <assemblyBinding xmlns='urn:schemas-microsoft-com:asm.v1'> <probing privatePath='obj'/> </assemblyBinding> </runtime></configuration>

C# and Java

Import C# assembly, e.g., to a subdirectory:> mkdir DegF> copy ..\oop\DegF.exe DegF> copy ..\oop\*.netmodule DegF

Multiple libraries could each be placed in their own subdirectory.

Additional single-file assembly:> vjc /out:DegC.exe /libpath:DegF /r:DegF.exe DegC.jsl IReversibleConversion.jsl ReversibleLinearConversion.jsl

•••

Additional assemblies:> vjc /t:library /libpath:DegF /r:DegF.exe IReversibleConversion.jsl> vjc /t:library /libpath:DegF /r:DegF.exe /r:IReversibleConversion.dll ReversibleLinearConversion.jsl> vjc /libpath:DegF /r:DegF.exe /r:ReversibleLinearConversion.dll /r:IReversibleConversion.dll DegC.jsl

vjc does not (yet?) support /addmodule; this significantly restricts how J# can be organized into assemblies.

ScopeAssemblies and types (class, struct, interface, enum) influence accessibility of names.

Source files and namespaces do not.

A file must contain a complete type.

internal: type is accessible only within assembly (default for classes).

public: type is accessible everywhere.

Compilation

/addmodule makes internal accessible, /r does not.

a.cs: class A { ... } // internal

b.cs: class B { A a; }

This is legal:> csc /t:module a.cs> csc /t:library /addmodule:a.netmodule b.cs

This is not:> csc /t:library a.cs> csc /t:library /r:a.dll b.cs

nmake Basicssmall scripting language.

build tool.

optimized command execution, based on source/target dependen-cies — hard to leverage for Java or C#.

table-driven (makefile).

part of .NET Framework SDK, patterned after the Unix tool.

download within Visual C++ Express or an older version.

Command Line> nmake name=value.. target..

reads makefile if any,

sets replacement text for variables if any,

executes commands to produce targets or first target.

makefile# commentname = value..

sets replacement text for variables.target.. : source.. ; commandlinetab commandlinetab commandline \ more of commandline..

specifies that targets depend on sources,

specifies command lines to create targets if they are older then the sources (if any).

Variables$n$(name)$(name:string=replacement)

all but single-letter names have to be in parentheses or braces.

$@ represents the current target.

$$@ represents the current target in a dependency.

$(@B) and $$(@B) represent the base name.

Command Lines

@ commandline suppresses echo,

- commandline ignores execution error.

target :: permits several sections with command lines.

Preprocessing!include path!if expression ..!else ..!endif

The expression has to use constants; strings may be compared.

!ifdef checks if a macro is defined.

Portability

nmake is available as part of SSCLI and can be used on FreeBSD and MacOS X.

!include can use an environment variable such as OSTYPE as part of the path to act differently on different platforms.

OSTYPE is set by bash on Unix. For the course examples it should be set to xp, e.g., in vsvars32.bat which is executed by the Visual Studio/Tools/Command Prompt.!if "$(OSTYPE)" == "xp"

can be used to conditionalize a makefile for a platform.

Windows FormsClassic graphical user interface.

Convert temperatures between Celsius and Fahrenheit.

Model-View-Controller design pattern.

Reuse model classes.

ViewObject(s) to handle interaction with the user.

Visual Studio creates code to create and configure the view.

Create a Windows Application project in Visual Studio.

Open View/Toolbox and create two GroupBoxes, each contain-ing one TextBox:

Properties

Select a visual object and change properties such as the Appear-ance of the Text of the GroupBox or the Design (Name) of the TextBox.

In Layout set Anchor to Top,Left,Right so that the boxes stay at the top of the form and grow horizontally with it.

Events

Select a TextBox and enter method names to handle events such as KeyPress or Leave:

Clear the method name for TextChanged.

ControllerObject(s) to route data between the view and the algorithm(s) implemented by the model object(s).

Visual Studio creates empty methods for all names entered to handle events and connects them to the view.

The methods need to be filled in.

Results in tight intergration of view and controller.

Makes the controller essentially non-reusable.

Insertions

Gui.csprivate void box_KeyPress (object sender, KeyPressEventArgs e) { switch (e.KeyChar) { case '\n': case '\r': post((TextBox)sender); ((TextBox)sender).SelectAll(); break; }}

Each case of a switch must be terminated, e.g., with break or goto case.

Additions

post() runs input through a model and back to a view:private IConversion c2f, f2c;private void post(TextBox from) { IConversion model = from == celsius ? c2f : f2c; TextBox to = from == celsius ? fahrenheit : celsius;

to.Text = model.Y(double.Parse(from.Text)) .ToString();}

•••

The constructor is changed to receive the group titles and the model to make the view/controller more reusable:public Gui (string fromName, string toName, IReversibleConversion model) { InitializeComponent(); groupBox1.Text = fromName; groupBox2.Text = toName; c2f = model; f2c = model.inverse();}

•••

The main program is changed to pass construction parameters:static void Main() { Application.Run(new Gui("Celsius", "Fahrenheit", new ReversibleLinearConversion(9.0/5.0, 32.0)));}

CompilationVisual Studio produces a program that requires no extra files.> mkdir lib> copy ..\oop\DegF.exe lib> copy ..\oop\*.netmodule lib> copy ..\java\DegC.exe lib> copy ..\java\*.dll lib> csc /lib:lib /r:DegF;DegC;IReversibleConversion /r:ReversibleLinearConversion Gui.cs

Gui.exe.config describes where the other assemblies can be found.

ObserversDesign pattern.

View observes Model.

Implemented with delegate and event.

Design PatternObservable holds state.

Observers are registered at observable.

When state changes, observable informs (all) observers.

Agreed-upon method (interface).

Variations

java.util.Observer, java.util.Observable

java.awt.event.*Listener

NeXT/Apple’s target/action paradigm: selectable observer, selectable method, method pattern.

NeXT/Apple’s delegate paradigm: object defers decision mak-ing, selectable observer, optionally implemented methods.

DelegateType declaration for callback function and queue of callbacks:delegate return-type name ( parameters );

Queue definition:name queue-name;

Queue operations (not thread-safe):queue-name = new name(other-queue-name);queue-name += new name(target.method-name);queue-name -= new name(target.method-name);

Callback to queue in order as added:queue-name(arguments);

Example

delegate.cs:class Observer { public void update (Observable sender) { Console.WriteLine("update"); }}delegate void QueueHandler (Observable sender);class Observable { public QueueHandler Queue; public void notifyObservers () { if (Queue != null) Queue(this); } static void Main () { Observable o = new Observable(); o.Queue += new QueueHandler(new Observer().update); o.notifyObservers(); }}

EventDelegate queue definition with external access restricted to add (+=) and remove (-=):event delegate-name queue-name;

By convention two arguments: source object and information object derived from System.EventArgs.

Accessors can be explicitly implemented:event delegate-name queue-name { add { .. value .. } remove { .. value .. }}

Anonymous MethodsAdded in C# version 2, motivated by Hejlsberg at PDC’03:delegate { method-body }delegate ( parameters ) { body }

Both can be used in the context of delegate creation:delegate return-type name ( parameters ); // declarationnew name(delegate { method-body }) // use(name)delegate { method-body } // syntactic sugar

Return value must match declaration.

Explicit parameters must match, otherwise no out parameters allowed.

a-delegate.cs

Closure

lambda.cs

Anonymous methods provide features similar to lambda in Scheme:(define d ((lambda (x) (vector (lambda (a) (begin (set! x (+ x a)) x)) (lambda (b) (begin (set! x (+ x b)) x)) ) ) 10))((vector-ref d 0) 1) ; sets x to 11 and returns 11((vector-ref d 1) 2) ; sets x to 13 and returns 13

Optimization

optimize.cs

Capturing a variable in an anonymous method extends its life-time (see The C# Programming Language):delegate void D ();D[] result = new D[3];for (int i = 0; i < 3; i++) { int x = i * 2 + 1; result[i] = delegate { Console.WriteLine(x); };}

Optimization is allowed to make x more global to instantiate just once:delegate void D ();D[] result = new D[3];int x;for (int i = 0; i < 3; i++) { x = i * 2 + 1; result[i] = delegate { Console.WriteLine(x); };}

Effectively there is now only one anonymous method.

Web FormsEssentially the client side of ASP.NET.

Web-Browser based graphical user interface, successor to ASP.

Convert temperatures between Celsius and Fahrenheit.

Event-loop paradigm for web page.

Reuse model classes.

ViewObject(s) to handle interaction with the user.

Visual Studio creates code to create and configure the view as a web Page, embedded in a Session and an Application.

Internet Information Server runs the code, serves the page, and posts the events coming back from the page.

Visual Studio 2005 uses a private web server for testing.

Example

Create a New Web Site in Visual Web Developer 2005 Express.

Select Visual C# and ASP.NET Web Site.

Default.aspx

The first form is called Default.aspx.

Select Design, open View/Toolbox and drag an HTML/Table into the form.

Type text and from Standard drag TextBoxes and two Buttons into the table cells.

Select the empty table cells and use Layout/Delete/Rows.

•••

Select each Button and TextBox and use View/Properties:

Change Text to convert to label the Buttons.

Change (ID) to celsius and fahrenheit -- the variable names for the TextBoxes in the code.

•••

The names can be checked in View/Document Outline:

f.aspx

Select Website/Add New Item and add a Web Form to the project. Check Place code in separate file.

•••

Drag two TextBoxes and an ImageButton into the form.

In Properties connect a local image file to the ImageButton and be sure to set the Width explicitly.

Set (ID) to the variable names celsius, button, and fahren-heit.

Partial Classes

Select View/Solution Explorer and right-click Default.aspx to select View Code.

Default.aspx.cs will contain C# code for event handling, etc.

Visual Studio writes the declarative part of a partial class in XML and keeps it hidden. The top right drop-down menu in the editor tab links to the .aspx file:

EventsDefault.aspx.cs

The class is derived from Page and (as a Control) supports the following events:

Apparently, the event handling methods must be named Page_Init, etc.

TextBox supports the TextChanged action, but a Button is required to actually post back to the server.

f.aspx.cs

ImageButton supports Click which is posted to the server; the event argument contains the mouse position in the Control.

CommunicationPage properties reference other objects describing the applica-tion:

Init object is createdLoad before each page requestPreRender right before renderingUnload before object is discardedDisposed last event

Application application state, collectionServer server, encode/decode, page selection, etc.Session session state, collection

Indexers

Indexed access to an object, similar to a property.

Overload of [ ].

Multiple signatures possible.result-type this [ type name ,.. ] { get { .. return .. } set { .. value .. }}

Examples: ArrayList, Hashtable, application and session state.

TestSelect Website/Add Reference and add libraries implementing the ReversibleLinearConversion.

Apparently, the compiler will only find references in .dll files.

Visual Studio 2005 beta provides a private webserver for testing which refuses external connections.

Web ServicesEssentially the server side of ASP.NET.

Service is usually offered over HTTP.

Used by means of a Web Reference.

Internally based on SOAP, but Visual Studio hides this.

Visual Studio 2005 uses a private webserver for testing.

Convert temperatures between Celsius and Fahrenheit.

ServiceCreate a New Web Site in Visual Web Developer 2005 Express.

Select Visual C# and ASP.NET Web Service.

Edit Code/Service.cs:using Edu.Rit.CS.ATS.Conversions;

[WebService(Namespace="http://www.cs.rit.edu/~ats/web-services/conversions/")]public class Service : System.Web.Services.WebService { IReversibleConversion c2f; IConversion f2c;

public Service () { c2f = new ReversibleLinearConversion(9.0 / 5.0, 32.0); f2c = c2f.inverse(); } [WebMethod] public double Celsius (double fahrenheit) { return c2f.Y(fahrenheit); } [WebMethod] public double Fahrenheit (double celsius) { return f2c.Y(celsius); }}

Test

Select Website/Add Reference and add libraries implementing the ReversibleLinearConversion.

Build/Build Website and Debug/Start.

Visual Studio generates a Service Description...

•••

...and a test page for each method:

•••

A reply is represented in XML:

Each test page sketches how the service could be tested using, e.g., telnet.

ClientCreate a Windows Application.

Design a form for temperature conversion, create KeyPress event handlers.

Web Reference

Run the service.

In Solution Explorer, right-click on References to Add Web Reference.

Enter the URL:http://localhost:port/Conversions/Service.asmx

where port points to the private webserver.

Change the web reference name to temperatures.

This creates a proxy class.

Connection

Edit Form1.cs:protected temperatures.Service model = new tempera-tures.Service();

private void toFahrenheit (object sender, KeyPressEven-tArgs e) {

switch (e.KeyChar) { case '\n': case '\r': fahrenheit.Text = model.Fahrenheit(double.Parse(cel-sius.Text)).ToString(); break; }}

The namespace temperatures was specified during Add Web Reference. The class Service is part of the service implementa-tion.

ArraysObject of class derived from System.Array.

Multi-dimensional.

Dimension fixed at construction.

Content initialized at construction, by default null value.

Common element type, value or reference.

Array of array.

Explicit and implicit conversions.

Constructiontype[] name = new type[dimension];type[] name = { value, .. };type[,] name = new type[dimension, dimension];type[,] name = { { value, value }, .. };

Can be combined but dimensions must match.

Dimensions must be int, uint, long, ulong, or implicitly con-vertible.

Array Creation Expressionnew type[dimension]new type[] { value, .. }

Also with more dimensions, etc.

Can be combined but dimensions must match.

Array of Arraytype[][,] name = { new type[dimension, dimension], .. };

Elements can be arrays (jagged array).

Also with initializers, etc.

Also as array creation expressions.

OperationsArray name is object name, i.e., reference.

Element reference by indexing.

Information and other operations inherited.

Conversions.

Referencesint[] iv = { 1, 2, 3 };int[,] jv = new int[3, 4];int[][] kv = new int[1][];int[][,] nv = new int[2][,];iv[2] = 4;jv[0,0] = 1;kv[0] = iv;nv[1] = jv;

Value elements are stored in array.

Reference elements are referenced by array elements.

Indices must be int, uint, long, ulong or implicitly convert-ible.

Informationint[] iv = { 1, 2, 3 };int[,] jv = new int[3, 4];int[][] kv = new int[][] { iv };iv.GetLength(0) // 3jv.Length // 12jv.Rank // 2kv[0].Length // 3kv.Rank // 1

System.Array

Useful static methods:BinarySearchClearCopyIndexOf, LastIndexOfReverseSort

Useful instance methods:ClearClone // shallow copyContainsCopyToEqualsGetEnumerator foreach (int val in new int[]{ 2, 4, 7 }) ..GetLengthToString

Conversionstring[] sv = { “a”, “b”, “c” };object[] ov = sv;sv = (string[]) ov;

Permitted only for reference arrays, if ranks are the same, and if the relevant reference element conversions exist.

Basically, to or from base class or interfaces.

Important for arrays as arguments.

Enumerationforeach ( type name in collection ) statement

collection implements IEnumerable or GetEnumerator().

System.Array and classes in System.Collections do.

IEnumerator provides MoveNext() and Current.

Not thread-safe.

Throws InvalidOperationException if collection is modified.

Column-order for multi-dimensional arrays.

ExpansionIEnumerator e = ((IEnumerable)collection).GetEnumerator();try { while (e.MoveNext()) { type name = (type)e.Current; statement }} finally { IDisposable disposable = e as IDisposable; if (disposable != null) disposable.Dispose();}

Iterators

Added in C# version 2, motivated by Hejlsberg at PDC’03:class List { IEnumerator GetEnumerator () { for (int i = 0; i < size; i++) yield return elements[i]; }}

Syntactic sugar to implement IEnumerator.

yield break; terminates enumeration.

•••IEnumerable Descending () { for (int i = size - 1; i >= 0; i--) yield return elements[i];}

IEnumerable Subrange (int from, int nElts) { for (int i = 0; i < nElts; i++) yield return elements[from + i];}

List items;foreach (Object o in items) { ... }foreach (Object o in items.Descending()) { ... }foreach (Object o in items.Subrange(10, 20)) { ... }

ContainersContainers as examples for class design and data structures.

(Over-)simplified.

Background for System.Collections.

Abstract DatatypeSet of values.

Operations on the values.

Axioms which the operations must observe.

Nothing about value representation and operation implementa-tion.

Performance depends on representation.

C#

interface only declares methods, including properties, events, and indexers. All members are public.

class defines class variables and methods and declares instance variables, i.e., representation and implementation.

Given a class one can use new to create values (objects) if a constructor is accessible.

abstract class may declare methods rather than define them.

abstract class cannot be instantiated.

ADT should be modeled as an interface. Values and axioms must be described verbally.

ISimpleContainerADT.

Manages access to other objects.

adt/doc/ADT

adt/ISimpleContainer.cspublic interface ISimpleContainer { object Add (object x); object Find (object x); object Sub (object x); int Count { get; }}

Boxing allows to manage int, etc. as well.

Axioms

Any kind of object can be added, found, and removed.

Find() cannot locate an object that has not been inserted with Add() earlier.

Object can no longer be found once it has been removed with Sub().

Sub() cannot remove anything that has not been inserted with Add().

Count is influenced by Add() and Sub().

•••

Can null be added, found, and removed?

Can the same object be added more than once?

If so, can it be removed more than once?

How could different copies be distinguished during Find()?

‘‘Same’’ object — identical or just equivalent?

Array.SimpleContainerFixed length array with object references.

count marks top.

null can be added.

Linear search.

Identity comparison.

Inserts equal values multiple times.

Removes equal values one at a time.

adt/doc/Array

adt/array/SimpleContainer.cs

locate() encapsulates search.

Failures reported as exceptions.

C#

SimpleTestEncapsulates testing.

Arguments or words from standard input.

adt/doc/ADT

adt/SimpleTest.cs

public class-name ( .. ) : base ( .. ) { .. }

invoke base class constructorpublic class-name ( .. ) : this ( .. ) { .. }

invoke same class constructorpublic class-name () { }

parameterless constructor, only provided if no other

public ?? type name ( .. ) { .. } virtual needs to be specified if... override ...will be used to override a method and... sealed ...can be added to disallow further override new must be specified to hideSystem.Text.StringBuilder

cheap to glue a longer string together

word addednull represents null- word removed. display container# display Count

C#

Execution> cd adt/array> nmake simple-containercsc /nologo SimpleContainer.cs \ ../SimpleIContainer.cs ../SimpleTest.csSimpleContainer null '' ats null . - null - ats .Edu.Rit.CS.ATS.ADT.Array.SimpleContainer count 3

ats

System.IO.TextReader System.Console.In

standard inputSystem.IO.TextWriter Console.Out

standard outputSystem.IO.TextWriter Console.Error

diagnostic outputWriteLine(”{0} {1}”, 10, ”$”)

formatted output== overloaded for stringstring.Intern() unique copy, efficient comparisontry { .. } catch { .. } finally { .. }

catches any exceptioncatch (exception-type)

catches particular type and subtypescatch (exception-type name)

provides accessSystem.Text.RegularExpressions.Regex

compiled pattern matching@”..” verbatim string, no \ escapesSplit cut string into substrings (awk)

sub ats: not foundEdu.Rit.CS.ATS.ADT.Array.SimpleContainer count 2

ats

ats cannot be removed: not identical character sequences.> SimpleContainer < ../Test.csUnhandled Exception: System.IndexOutOfRangeException..

GenericsAdded in C# version 2, motivated by Hejlsberg at PDC’03:

Classes, interfaces, delegates, and methods can depend on type parameters.class X<T ,..>: .. where .. { .. }interface X<T ,..>: .. where .. { .. }delegate result X<T ,..> ( .. ) where .. ;access result X<T ,..> ( .. ) where .. { .. }

Useful, e.g., to restrict containers and avoid casts and boxing.

System.Collections.Generic.

Constructed types expanded by JIT compiler.

IContainer

Restricts elements to one class.

adt/doc/ADT

adt/IContainer.csusing System.Collections.Generic;public interface IContainer<T>: IEnumerable<T> { T Add (T x); T Find (T x); T Sub (T x); int Count { get; }}

Cannot alias an open constructed type.

Array.Container

Fixed length array with generic references.

adt/doc/Array

adt/array/Container.cs

locate(): Unconstrained objects cannot be compared.

Main() cannot be in a generic class declaration.

Test

adt/doc/ADT

adt/Test.cs

Expects a constructed adt/IContainer.

Closed constructed type can be aliased.

Execution> cd adt/array> nmake containercsc /nologo Container.cs \ ../IContainer.cs ../Test.csContainer null '' ats null . - null - ats .Container[[System.String] ..] count 3

ats

sub ats: not foundContainer[[System.String] ..] count 2

ats

Constructed type shows element type.

Array.BagSubclass of Array.Container.

Fixed length array with object references, replaced by longer array on overflow.

adt/doc/Array

adt/array/Bag.cs

override of Add(), intercepts the overflow exception and replaces the current array.

C#

base can be used to block searching for an override:class A { virtual void a () { }}class B: A { void b () { base.a(); // definitely found in A a(); // found in A or in C or beyond} }class C: B { override void a () { }}

Operator OverloadingSome operators, including conversions, can be overloaded.

static, i.e., located by compile-time(!) type match and no override.

Only in the own class.

Severe confusion is still possible.

adt/doc/Array

adt/array/Abuse.cs

this.method( .. ) start search in class of receiver.base.method( .. ) start search above class in which this code

appears.

Unary Operators

Only for unary + - ! ~ ++ --, true and false:class type { static rtype operator name (type x) { .. }

++ and -- must return the argument type.

true and false must return bool.

true is used in boolean expressions (if, do, for, while, ?:).

Binary Operators

Only for binary + - * / % & | ^ << >>, == and !=, > and <, >= and <=:class atype { // or btype static rtype operator name (atype a, btype b) { .. }

name= is implicitly overloaded by overloading name.

&& is implicitly overloaded by overloading truetrue(a) ? true(b) : false

or by overloading type &(type, type) and false(type)false(a) ? a : &(a, b)

|| is implicitly overloaded by overloading truetrue(a) ? true : true(b)

or by overloading type |(type, type) and true(type)true(a) ? a : |(a, b)

Conversion Operatorsclass type { static implicit operator rtype (type x) { .. } static explicit operator rtype (type x) { .. }

Either type cannot be an interface or a base class.

explicit is called with a cast.

implicit calls are invisible.

Equalityadt/array/equal.cs

For equivalence use (and override) Equals.

For identity use ReferenceEquals or(object)x == (object)y

null is only equal to null.class object { static bool ReferenceEquals (object a, object b)

determines identity.static bool operator == (object a, object b)

determines identity and can be overloaded.class object { static bool Equals (object a, object b)

defers to... virtual bool Equals (object b)

determines identity until override.

Array.SetSubclass of Array.Bag.

Unique insertion based on identity.

adt/doc/Array

adt/array/Set.cs

override of Add(), uses Find(), intercepts the not found exception and then asks the base class to insert.

Array.EquivalenceSetSubclass of Array.Set.

Unique insertion based on equality.

adt/doc/Array

adt/array/EquivalenceSet.cs

override of locate(), uses System.Array.LastIn-dexOf(), throws exception if not found.

Hash.ContainerOpen hashing to select IContainer.

Features depend on container.

adt/doc/Hash

adt/hash/Container.cs

Abstract base class with factory method to create containers.

C#

object.GetHashCode(), but not for null.

Should not contradict Equals().

GetHashCode() is unique for unique strings(?).

% can produce negative results for negative left operands.

Math defines overloaded mathematical functions.

Iterator implementations can use iterators.

Hash.BagCombines hashing with Array.Bag:

Fixed length array with object references, replaced by longer array on overflow.

null can be added.

Linear search in selected container.

Identity comparison.

Inserts equal values multiple times.

Removes equal values one at a time.

adt/doc/Hash

adt/hash/Bag.cs

Hash.SetCombines hashing with List.Set.

Linear doubly-linked list of object references.

null can be added.

Identity comparison.

Inserts equal values once.

adt/doc/Hash

adt/hash/Set.cs

Hash.EquivalenceSetCombines hashing with Tree.Set.

Sorted binary tree of object references.

null can be added.

Equality comparison.

Inserts equal values once.

adt/doc/Hash

adt/hash/EquivalenceSet.cs

Constraints need to be enforced.

List.BagLinear doubly-linked list of object references.

null can be added.

Identity comparison.

Multiple insertion.

Removal one at a time.

adt/doc/List

adt/list/Bag.cs

Container hides element representation.

C#

Bag and Link both use public members of Link.

No special cases: ring with header element and Unlink().

ToString() can be tricky in a ring.

Links() implements iteration over the linked list elements.

class x { class y {

inner class, access to static things.

class x<T> { class y {

nested class can use outer type parameter (or can itself be generic).

List.SetSubclass of List.Bag.

Unique insertion based on identity.

adt/doc/List

adt/list/Set.cs

override of Add(), uses Find(), intercepts the (different!) not found exception and then asks the base class to insert.

List.EquivalenceSetSubclass of List.Set.

Unique insertion based on equality.

adt/doc/List

adt/list/EquivalenceSet.cs

override of locate() could use object.Equals(,).

Tree.SetSorted binary tree of null and IComparable values.

Unique insertion based on CompareTo().

adt/doc/Tree

adt/tree/Set.cs

Container hides element representation.

C#

Inner class can extend encompassing class.

Unroot() very much simplifies deletion.

Count is an interesting recursion.

GetEnumerator() is a seemingly iterative inorder traversal.

locate() uses closure: the IResult object can be asked to implement the necessary operation in the appropriate context which is frozen at construction.

Found and NotFound simulate member classes.

ThreadsProcess: execution of an assembly.

Thread: program counter and stack within process.

Management.

Synchronization.

System.Threading

Thread

Manythreads/many.cs

Thread manage one program counter.ThreadPool (provided by system.)ThreadStart delegate to wrap program

counter.ThreadInterruptedException happens on Interrupt().Monitor functions for Hoare-style syn-

chronization.Interlocked functions for atomic opera-

tions.Mutex interprocess synchronization.

CurrentThread static, returns object for current thread.Sleep(msec) static, immediately affects current thread.Start() activates program counter.Suspend() suspends receiver at safe point.Resume() reactivates receiver.Interrupt() sends exception once receiver is sleeping,

waiting, or joining (not suspended).Abort() terminates receiver, can be intercepted.Join() waits for receiver to terminate.IsBackground application terminates if only background

threads remain.

creates threads that write command line arguments.

Randythreads/randy.cs

tries to let the last thread write a newline.

Morsethreads/morse.cs

tries to synchronize in order to let the last thread write a newline.

Monitor

Reference types only.

Anythreads/any.cs

uses a monitor to solve a one-producer-many-consumers prob-lem.

Enter(object) one at a time, usually as lock(object).TryEnter(object) false if not possible.Exit(object) leave, let next one in.Wait(object) wait until pulsed, let next one in.Pulse(object) pulse one waiting thread.PulseAll(object) pulse all waiting threads.

Semaphoresthreads/semaphore.cs

Dijkstra’s classical concept:

P() decrements and blocks waiting on a nonnegative value.

V() increments and releases.

threads/producer.cs

uses semaphores to solve a one-producer-many-consumers prob-lem.

C#

Inner class is implicitly static.

Inner class can only access encompassing static things.

Inner class can simulate Java member class by passing context object as a parameter.

However, static access to context’s state must be arranged explicitly.

Dining PhilosophersA philosopher is (cogito ergo sum) and eats. Five share five forks, but each needs two to eat.

Deadlock problem.

One approach: yield fork if unsuccessful. One philosopher has alternate grabbing order.

threads/philosopher.cs

Input/OutputBidirectional byte streams.

Unidirectional readers and writers with encodings.

Format providers for cultural specifics.

System.IO

Other classes for directories, files, and paths.

Stream abstract, bidirectional, bytes.FileStream Stream on a file, can be asynchronous.MemoryStream Stream on a byte array.BinaryReader reads encoded binary values.BinaryWriter writes encoded binary values and strings.TextReader abstract, reads encoded characters.TextWriter abstract, writes encoded characters.StreamReader TextReader on Stream or file.StreamWriter TextWriter on Stream or file.StringReader TextReader on string.StringWriter TextWriter on string.

Stream

Other methods for asynchronous operation.

Close disconnects, releases resources.Flush may emit buffered data.IDisposable.Dispose() releases resources (not required).CanRead true if reading is supported.Read reads into byte array, returns count.ReadByte returns (positive) byte.CanWrite true if writing is supported.Write writes from byte array.WriteByte writes one byte.CanSeek true if positioning is supported.Length may return length of stream in bytes.SetLength() may set Length.Position may get or set current position.Seek() may get or set current position.

using

I/O connections (and threads) are precious resources.

IDisposable interface, intended to release resources as soon as possible.

Finalizers are executed by garbage collection — too late or never.using (resource) statement

syntactic sugar for:resource;try { statement} finally { if (resource != null) resource.Dispose();}

Implementing Dispose() is tricky.

GrepBlueprint for Unix filter program.

Search for lines matching pattern.

Search standard input or files specified on command line.

io/grep.cs

Can be executed by thread.

GrepAllSearch for lines matching several patterns in any order.

Implemented as Grep objects linked by pipes and executed by threads.

io/grepall.cs

Grep is subclassed because a pipe writer needs to close the pipe for the pipe reader to receive and of file.

Example for using().

PipeRing-buffer with Stream interface.

Configurable synchronization behaviour.

io/pipe.cs

Implements Dispose() as suggested by the Nutshell book.

SerializationPersistent object graphs.

Binary and XML (SOAP) formatting.

Transmission to files and across networks.

SoapFormatter in version 1.1 possibly defective.

AttributesImplicit selection of state.

serialize/data.cs circular linear listserialize/in.cs deserializes, optionally /d:SOAPserialize/out.cs serializes, optionally /d:SOAP

C#

ISerializableExplicit encoding of state.

[Serializable] marks a class for transmission.[NonSerialized] exempts a field from transmission.IFormatter interface: Serialize(stream, obj) output.Deserialize(stream) input.BinaryFormatter binary representation.SoapFormatter XML representation.

serialize/data.cs /d:ISERIALIZABLE

C#

Proxies

Replacement object at other end of a network connection.

SurrogatesPlugins for the formatting process.

Replacement on output, resolution on input.

Implementation in version 1.0 defective.

ISerializable interface, in addition to [Seri-alizable]:

GetObjectData(info, ctxt) output, must add field values to info.

<constructor>(info, ctxt) input, must initialize field val-ues from info.

StreamingContext describes transport layer.SerializationInfo collection of values:AddValue(key, value) output.GetValue(key, type) input.GetInt32(key) input of primitives.FullTypeName output to create proxy.AssemblyName output to create proxy.

serialize/data.cs /d:ISERIALIZABLE /d:PROXY

serialize/proxy.cs replacement

C#

Distributed Objects 101

client calls method at proxy.

proxy has same interface as service.

proxy communicates across network.

Must be able to map service uniquely across network and back.

SurrogateSelector subclass to override:GetSurrogate(type, ctxt, out sel) find surrogate for type.ISerializationSurrogate interface:GetObjectData(obj, info, ctxt) output, fill info.SetObjectData(obj, info, ctxt) input, return object.

serialize/inout.cs demos several roundtrips over pipe.serialize/surrogate.cs implements surrogates.

New Proxy

Return to Service

Return to Proxy

etc.enum.

Operators: as is typeof checked unchecked.

struct: value types.

const: like readonly but implicitly static.

Destructor: ~Class() { .. } is Finalize method.

Unsafe code: unsafe, fixed, stackalloc, sizeof, -> * &.

Lots of .NET, e.g., remoting and security.

enumCounts as a value type.

Inherits from System.Enum.

Integer operations (comparison, arithmetic).

[Flags]: values should be bit-masks and are pretty-printed.

enum/enum.cs

enum type-name [: integer-type] { name [= value] , ..}

creates named integer constants

type-name.name references

Operatorstype-checking: as is typeof

arithmetic-checking: checked unchecked

Type Checking

Arithmetic Checking

Value TypesAssigned and passed by value.

Boxed by implicit conversion, unboxed by explicit conversion, i.e. can be used in collections.

All ‘primitives’ like bool, char, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal.

System.Int32 etc. define the ‘primitives’.

value as type downcast, converted or null.value is type-name true if compatible.typeof value corresponding Type object.

checked ( expression )checked { statements }

throws exception on overflow.

unchecked ( expression )unchecked { statements }

ignores (wraps) overflow, even for constants at compile time.

csc /checked+ /checked- turns on/off for runtime.

structstruct type-name [: interface ..] { member ..}

Implicitly sealed.

Never abstract.

No destructor.

No explicit parameterless constructor.

Constructors, if any, must assign to all fields.

Cast to interface is boxing.