Sei sulla pagina 1di 44

www.manuelscapolan.

it

LEZIONE 03
.NET Framework Class Library

File I/O

Exception Handling

Collections

Generics
… and much more!
2
Collezioni di oggetti

• Con gli Array possiamo gestire insiemi


non ordinati di elementi accessibili
tramite indice
• La Framework Class Library ci mette a
disposizione altri tipi di collezioni per
poter gestire:
– Insiemi ordinati
– Insiemi accessibili per chiave
– Insiemi di coppie chiave/valore
– Insiemi “tipizzati”

3
Collezioni di oggetti

• Tipi di collezioni in System.Collections:


Tipo Caratteristiche
ArrayList Consente di implementare l'interfaccia IList utilizzando una matrice la cui
dimensione aumenta dinamicamente in base alle necessità
Hashtable Rappresenta un insieme di coppie chiave/valore organizzate in base al codice
hash della chiave.
BitArray Consente di gestire una matrice compatta di valori di bit, rappresentati come
Boolean, dove true indica che il bit è attivo (1), mentre false indica che il bit è
inattivo (0).
SortedList Rappresenta un insieme di coppie chiave/valore, ordinate in base alle chiavi e
accessibili per chiave e per indice.
Stack Rappresenta un semplice insieme non generico LIFO (Last-In, First-Out) di
oggetti.
Queue Rappresenta un insieme di oggetti FIFO (First-In First-Out).

4
Hashtable

• Rappresenta un insieme di coppie


chiave/valore organizzate in base al codice
hash della chiave

Coppia chiave/valore elemento di


una hashtable

5
Stack e Queue

• Stack: insieme di oggetti con accesso LIFO


(Last-In, First-Out)
push
pop

• Queue: insieme di oggetti con accesso FIFO


(First-In, First-Out)

enqueue dequeue
6
BitArray

• Rappresenta un insieme di valori booleani

• Permette di eseguire delle operazioni di


confronto bit a bit:
– And
– Or
es. bitArray1.And(bitArray2)
– Xor
– Not
bitArray1 viene modificato
dall’operazione di confronto!

7
BitArray: un esempio

• Voglio che sia bello, ricco e famoso!

8
IEnumerable e ciclo foreach

• Il foreach permette di navigare una


collezione di oggetti uno dopo l’altro
• Possiamo farlo anche con le nostre classi
implementando l’interfaccia IEnumerable:

9
IEnumerable e IEnumerator
• Definire un enumeratore personalizzato:

10
Generics

• Con i generics riesco a separare la logica di


un algoritmo dal tipo di dato sul quale viene
applicato (“algorithm reuse”)

Devo fare un cast

Tipo ”aperto” (non può


essere istanziato)
E’ tipizzato!

11
Dichiarare un tipo generico

• Per dichiarare un tipo generico bisogna


specificare dopo l’identificativo della classe
un tipo T tra le parentesi angolate < e >

Generalmente i tipi generici


hanno come nomi T, U, V,
etc., ma posso chiamarli
come voglio …

• Nel momento in cui vado a inizializzalo


andrò a specificare il tipo concreto

12
Collezioni “generiche”

• Collezioni in System.Collections.Generic:
Tipo generico Controparte non generica

List<T> ArrayList

Dictionary<Tkey, TValue> Hashtable

SortedDictionary<Tkey, Tvalue> SortedList

(nessuna) BitArray

LinkedList<T> (nessuna)

Stack<T> Stack

Queue<T> Queue

13
Nullable<T>

• Vi ricordate dei Nullable Types?


• Sono realizzati tramite i generics!
• La logica è comune per tutti i tipi: verificare
se esite un valore assegnato ad una variabile
di tipo Value Type

int?
Do you remember?

14
Benefici dei generics

• L’utilizzo dei generics porta ad avere i


seguenti benefici:
– Incapsulamento dell’algoritmo
Separo la logica dai dati nascondendo l’algoritmo
all’utilizzatore
– Verifica a compile-time sui tipi
Il compilatore previene cast non validi

– Codice più pulito


Non devo fare cast o istanziare variabili intermedie
– Migliori performance
Con i value type non ho bisogno di fare boxing/unboxing

15
Verifichiamo le performance

• Verifica delle performance con aggiunta e


accesso per indice:
ArrayList VS List<T>

16
Verifica su T

• Il compilatore verifica che l’utilizzo di T valga


per tutti i tipi (presenti e futuri)
Tutti i tipi hanno un
metodo GetType perché
ereditato da object

NON tutti i tipi hanno


un metodo CompareTo,
solo quelli che
implementano
l’interfaccia IComparable

17
Vincoli sul tipo T

• Se voglio definire del codice generico solo


per un insieme ristretto di tipi, devo porre dei
vincoli su T attraverso la parola chiave where

TIP: Impostare sempre il


vincolo più stringente

• Vincolo sul costruttore:

18
Generic Methods

• I generics possono essere anche applicati ai metodi


ed essere utilizzati come parametri e valori di ritorno
compile-time runtime

Chiamata per inferenza di tipo

• Utilizzo di T come variabile

19
Ereditarietà con i generics

• Le classi generiche sono tipi a tutti gli effetti


e come tali possono essere ereditate, con
qualche precisazione:
– Se una classe non-generica estende una classe
generica, la derivata deve specificare il tipo di
parametro
– Se la classe base definisce un metodo generico
astratto o vrtuale, la derivata deve eseguire
l’override specificando il tipo di parametro
– Se una classe derivata è anch’essa generica
può riutilizzare il tipo di parametro della classe
base

20
Ereditarietà con i generics

• L’ereditarietà tra classi generiche non


comprende automaticamente anche i tipi

21
Covarianza e Controvarianza

• La covarianza è la possibilità di utilizzare un


tipo più derivato di quello specificato in
origine
– Si ottiene nei tipi generici aggiungendo alla
definizione del parametro la parola chiave out

• La controvarianza è la possibilità di utilizzare


un tipo meno derivato
– Si ottiene nei tipi generici aggiungendo alla
definizione del parametro la parola chiave in
22
Tuple

• La “Tupla” è un insieme di dimensioni fisse di


dati tipizzati eterogenei
• Può essere utilizzata per far tornare ad un
metodo più di un valore

23
Esercizi

1) Riscrivere l’esempio del “tempo di


cottura” della lezione precedente
utilizzando i generics
2) Scrivere una classe generica che
permetta di distribuire le informazioni
di una lista (generica anch’essa) in n
parti uguali. Il numero di parti viene
passato al costruttore

24
Gestione delle eccezioni

• Una eccezione è una condizione di errore


che interrompe il normale flusso operativo
del programma
• L'eccezione viene propagata nello stack di
chiamate finché non viene gestita
• Le eccezioni non gestite (unhandled
exception) vengono riportate dal sistema
direttamente nell’interfaccia utente

25
Catturare una eccezione

• E’ possibile catturare le eccezioni che si


verificano in un blocco di codice attraverso
il costrutto try … catch

Blocco di codice
sotto controllo
delle eccezioni

Cattura l’eccezione
specifica Gestione dell’errore
specifico

Eccezione di base da cui derivano tutte


le eccezioni
26
Tipi di eccezioni

• E’ possibile specificare diversi catch in


cascata per gestire diversi tipi di eccezione

Deve essere lasciato


per ultimo perché più
generico

27
“Pulizia finale” con Finally

• Alle volte, indipendentemente dall’errore


che viene sollevato, è necessario eseguire
del codice, lo possiamo fare inserendolo in
un blocco finally

28
System.Exception

• Classe base per tutte le eccezioni:


Membro Tipo Descrizione
Message String Descrizione tecnica dell’errore. Normalmente viene salvata in
un log e non è buona norma mostrarla all’utente

Data Dictionary Dizionario di parametri passato da chi solleva l’eccezione a


chi la gestisce

Source String Nome dell’assembly che ha generato l’errore

StackTrace String Contiene nomi e firme delle chiamate ai metodi dal punto in
cui è stato generato l’errore

TargetSite MethodBase Metodo che ha scatenato l’errore

InnerException Exception Rappresenta l’eccezione precedentemente sollevata se quella


corrente è stata sollevata in un altro gestore

29
“Sollevare” una eccezione

• Se in un nostro metodo non riusciamo a


completare un’operazione e vogliamo
esplicitare con un errore questa condizione
è possibile ritornare al chiamante una
eccezione con la parola chiave throw
• In questo caso dobbiamo scegliere quale
tipo di eccezione sollevare e un messaggio
che spiega perché non è stato possibile
completare l’operazione

30
Definire una nuova eccezione

• Oltre alle eccezioni fornite con la Framework


Class Library possiamo definire le nostre
eccezioni ereditando dalla classe Exception
(o da un’altra classe più specifica)

31
Gestione delle eccezioni – Tips

• Validare i parametri di ingresso al metodo


• Non utilizzare il throw come modo per effettuare un
ritorno dal metodo corrente
• Utilizzare dove possibile il finally per pulire le risorse
• Non eseguire il catch di tutto (vedi Exception)
• Se si conosce il motivo di una eccezione
comunicarlo all’utente
• Implementare dove possibile un ripristino di una
situazione consistente
• Evitare di esporre con le eccezioni dettagli
implementativi, eventualmente eseguire un re-
throw di una eccezione differente

32
System.IO: lavorare con i file

• In System.IO troviamo una serie di classi per


gestire gli input-output da file e in memoria
Tipo Descrizione
BinaryReader These classes allow you to store and retrieve primitive data types (integers,
BinaryWriter Booleans, strings, and whatnot) as a binary value.
This class provides temporary storage for a stream of bytes that you can
BufferedStream
commit to storage at a later time.
You use these classes to manipulate a machine’s directory structure.
Directory
The Directory type exposes functionality using static members, while
DirectoryInfo
the DirectoryInfo from a valid object reference.

DriveInfo This class provides detailed information regarding the drives

You use these classes to manipulate a machine’s set of files. The File
File
type exposes functionality using static members, while the FileInfo
FileInfo
type exposes similar functionality from a valid object reference.

33
System.IO: lavorare con i file

Tipo Descrizione
This class gives you random file access (e.g., seeking capabilities) with
FileStream
data represented as a stream of bytes.
This class allows you to monitor the modification of external files in a
FileSystemWatcher
specified directory.
This class provides random access to streamed data stored in memory
MemoryStream
rather than a physical file.
This class performs operations on System.String types that contain file
Path
or directory path information in a platform-neutral manner.
StreamWriter You use these classes to store (and retrieve) textual information to (or
StreamReader from) a file. These types do not support random file access.
Like the StreamReader/StreamWriter classes, these classes also work
StringWriter
with textual information. However, the underlying storage is a string
StringReader
buffer rather than a physical file.

• Tra le altre classi troviamo le classi astratte


Stream, TextReader e TextWriter
34
Directory(Info) e File(Info)

• Le classi Directory e File consentono di


operare sul file system tramite metodi statici,
mentre le controparti FileInfo e DirectoryInfo
lavorano a livello di istanza

Lista di file presenti


in una directory
Creazione di un
nuovo file

35
Leggere e scrivere: un modo veloce

• Ci sono molti modi per lavorare con i file uno


di questi è attraverso i metodi ReadAllLines()
e WriteAllLines()

Con WriteAllLines
se non esiste il file
viene creato in quel
momento

36
La classe astratta Stream

• Uno stream rappresenta una sequenza di


dati scambiati tra una sorgente e una
destinazione
• La classe astratta System.IO.Stream
definisce una serie di membri a supporto
delle interazioni sincrone e asincrone con lo
storage (es. file o locazioni di memoria)
Alcuni membri della classe asratta Stream
CanRead
Length
CanWrite Close() Flush()
SetLength()
CanSeek

Read() Write()
Seek() Position
ReadByte() WriteByte()

37
FileStream

• La classe FileStream è l’implementazione


della classe Stream per lo streaming su file

Codifica da
string a byte

Scrittura byte sullo stream

Lettura byte a byte


con ReadByte()

Decodifica da
byte a string

38
StreamWriter

• La classe StreamWriter definisce un wrapper


sullo stream per scrivere dati in formato testo
• Deriva dalla classe astratta TextWriter:
Membro Descrizione
Closes the writer and frees any associated resources. In the process, the
Close()
buffer is automatically flushed
Clears all buffers for the current writer and causes any buffered data to
Flush()
be written to the underlying device;. It does not close the writer
This property indicates the newline constant for the derived writer
NewLine class. The default line terminator for the Windows OS is a carriage
return, followed by a line feed (\r\n)
This overloaded method writes data to the text stream without a
Write()
newline constant
This overloaded method writes data to the text stream with a newline
WriteLine()
constant

39
Scrivere su file di testo

• Vediamo la classe StreamWriter in azione:


All’uscita dal blocco di istruzioni
chiude il file e rilascia le risorse Crea un nuovo file o apre in
scrittura quello esistente

Scrivo del testo sul file Inserisco nel file una nuova riga

NOTA: Con Autoflush = true la scrittura sul file avviene dopo ogni write, con
Autoflush = false (predefinito) la scrittura viene fatta al momento del Close()

40
StreamReader: leggere da file di testo

• Con la classe StreamReader leggiamo il


contenuto del file di testo
Membri della classe StreamReader
Peek() Read() ReadLine()

ReadBlock() ReadToEnd()

Legge tutto il file dalla posizione corrente


Mette in un buffer il numero di caratteri fino alla fine e mette tutto in una stringa
specificato come parametro

Posso creare una nuova


istanza di StreamReader
specificando il percorso
del file da leggere
Null == EOF

41
StringWriter e StringReader

• Posso utilizzare le classi StringWriter e


StringReader per scrivere e leggere stringhe
di caratteri in memoria

Scrivere testo
in memoria

Leggere testo
dalla memoria

42
Esercizi

3) Scrivere una funzione ricorsiva che


visualizzi sulla console la struttura di file
e cartelle di una directory specificata
(con la possibilità di definire un
numero di livelli di profondità)
4) Scrivere un metodo che inserisca in
un file di testo i numeri di riga

43
Contacts MANUEL SCAPOLAN
website: www.manuelscapolan.it
twitter: manuelscapolan
e-mail: info@manuelscapolan.it

Credits
Le immagini contenute in questa presentazione
hanno licenza Creative Commons

Slide 2 : http://www.flickr.com/photos/ajc1/4663140532

44