Jump to content
  • C# (C Sharp) Lezione #1 - Programmazione Guida passo per passo


     Share

    Il C# (si pronuncia see sharp) è un linguaggio di programmazione orientato agli oggetti sviluppato da Microsoft all'interno dell'iniziativa .NET, e successivamente approvato come standard dalla ECMA (ECMA-334) e ISO (norma ISO/IEC 23270).

    La sintassi e struttura del C# prendono spunto da vari linguaggi nati precedentemente, in particolare Delphi, C++, Java e Visual Basic.

     

    In questa guida vediamo la versione 7.2 di C#.

     

    .Object-Oriented, sintassi alla C (graffe, int, for, ...)

    .Distinzione fra tipi valore e reference

    - boxing e unboxing

    - le stringe sono oggetti immutabili 

    .Ereditarietà singola per classi, ma multipla per le interfacce. Supporta i generici (metodi, classi, e interfacce)

    .Costruttori per inizializzare gli oggetti

    .Oggetti creati con new, garbage collected

    .Gestione degli errori tramite meccanismo di eccezioni

    .Compilato per un'unica architettura (virtuale)

     

    Statement

    .if, while, do while, for, {}, expression-stmt (espresesione seguita da ";"), dichiarazioni di tipo sono (quasi) uguali.

    .foreach(T v in exp) che in Java è for(T v : exp)

    .goto (permesso in certi casi), sostanzialmente sostituisce break/continue etichettati

    .synchronized è diventato lock

    .Lo switch

     - non supporta il "fall-through" se il case non è completamente vuoto

     - i case possono essere string literal (ora anche in Java 7)

     - (supporta anche i pattern matching nei case)

     

    	Java						C# (in realtà: .NET)
    java.lang.Object:			System.Object:
    	-toString					-ToString
    	-equals						-Equals
    	-hashCode					-GetHashCode
    	-(finalize)					-(finalize)
    	-(altri metodi coi thread)
    java.lank è un package		System è un namespace (java -> classe di java.lang)
    	-che si importano			-si dichiarano con namespace e si usano con using

     

    Vediamo il primo codice Ciao Mondo:

     

    namespace ConsoleApplication {
    	using System;
    
    public class Program {
    	public static void Main(string[] args) {
          Console.WriteLine("ciao mondo");
          Console.ReadLine();
    	}
    }}

     

    si può usare il comando

    using static System.Console;

    Permette di usare le classi dichiarate in System senza qualificarle pienamente Console invece di System.Console;

    Meccanismo analogo per le classi permette di accedere ai membri statici senza esplicitare il nome della classe WriteLine invece di Console.WriteLine

     

    Modificatori di Accesso

     

    Le classi possono avere questi modificatori di accesso vediamo il confronto con Java:

     

    Java		c#
    .public		.public
    .protected	.protected - classe e sottoclassi
    .(friendly)	.---
    .---		.internal - stesso assembly (dll o exe)
    .---		.internal protected - protected o internal
    .---		.private protected - protected e internal (sic)
    .private	.private

     

    public: accessibile a tutti

    private: accessibile solo alla classe

     

     

    Ereditarietà

     

    Vediamo prima come si fa in Java prima:

     

    Java
    .class C1 extends C2
    	implements l1, l2, l3 {
    		C1() super(...) ...
    		C1 (int x) { this(...) ...
    
    interface l extends l1, l2, l3, ..

     

    In Java le interfacce possono avere campi costanti (final static)
    ora vediamo l'ereditarietà in C#:

     

    c#
    class C1 : C2, I1, I2, I3 {
    	C1 : BASE (...) { ...
    	C1 (int x) : this (...) { ..
    
    interface I : I1, I2, I3 ...

     

    In C# le interfacce contengono solo metodi (astratti e pubblici, come in Java)

    Per convenzione, iniziano tutte con I : IPippo, IPluto, ecc..

     

     

    Metodi virtuali o no?

     

    JAVA:

    . default: dispatch dinamico

    . override senza modificatori (ma introdotta @Override)

    . final rende il dispatch statico, ma evita anche ogni ri-definizione nelle sottoclassi

     

    Binding: associazione di un nome a un'operazione (usando, per esempio, i tipi degli operandi/argomenti) in Java sempre statico

    in C# Dynamic binding -> dynamic dispatch (non viceversa!)

    Dynamic dispatch: selezione di una particolare implementazione per operazione polimorfa

     

    C#:

     

    . default: dispatch statico

    . per avere dispatch dinamico: virtual

    . quando il metodo esiste già, richiesto override o new (che è default, ma con warning)

    . una ridefinizione di metodo può essere marcata con sealed per evitare altre ridefinizioni

    . classe sealed è come final in Java

     

     

    Metodi implementati

     

    Se I1 e I2 hanno un metodo m, e C le implementa entrambe, posso implementare diversamente I1.m e I2.m?

     

    In Java No, è richiesto un metodo pubblico chiamato m e ce ne può essere solo uno

    In C# si, grazie all'implementazione esplicita di interfacce 

    public class C : I {
    	int I.Met() {
    		return 1;
    	}
    }

    Non ci va nessun modificatore e il metodo risulta inaccessibile attraverso il tipo C.

     

    Metodi locali

     

    I metodi locali sono sempre privati, dentro a Met stesso, come convenzione di stile si mettono in fondo

    Non sono visibili agli altri metodi e chi deve capire la classe sa che non ha bisogno di leggerli se non vuole entrare nei dettagli di Met

     

    Runtime Type Identification/Cast

     

    in Java abbiamo;

    • exp instanceof T
    • (T)exp
    • Object t = exp;    t instanceof T ? (T)exp : (T)null

     

    in C# abbiamo:

    • exp is T
    • (T)exp
    • exp as T

     

     

    Costanti

     

    Java

    .Campi final static

    C#

    .Modificatore readonly analogo a final

    .Modificatore const, usabile con tipi numerici ed enumerazioni, indica una costante a tempo di compilazione

     

     

    Eccezioni

     

    Entrambi hanno try/catch/finally e una gerarchia di eccezioni con radice (java.lang/System).Exception e membri analoghi StackTrace/InnerException

    Ma C# non ha le eccezioni controllate, quindi non ha la clausola throws nelle intestazioni dei metodi (e non vi costringe a dichiarare/catturare)

     

    Le eccezioni si catturano per gestirle 

    catch (Exception e)
    {Console.WriteLine(e.Message);}

    eventualmente si risollevano

    Catch (Exception e)
    	{throw new 
    Exception (e.Message); }

    magari cambiando tipo

    catch (Exception e)
    	{throw new
    MyException(e.Message);}

     

    Ok solo per console applications

    Altrimenti:

    catch (Exception e)
    {
    	Debug.WriteLine(e.Message);
    }

    cosi si conserva history

    Oppure usando gli exception filter:

    private static bool NotifyAndContinue(Exception e){
    	/*do logging/console writing*/
    	return false;
    }
    ...
    catch (Exception e) when (NotifyAndContinue(e))
     { }

    volendo cambiare tipo

    catch (Exception e)
    	{throw new MyEception(e);}

     

     

    Tipi primitivi/valore

     

    Java:

    boolean, char, int, long, float, double, ...

    C#:

    bool, char, int, long, float, double, (unsigned) uint, ulong, ...

    ma int è un alias di Int32, ulong di UInt64, ecc...

    - object è un alias di Object

    - string è un alias di String

     

     

    Tipi in .NET

     

    I linguaggi supportati dal .NET framework quali C# e VB si dice che sono strongly-typed, ossia fortemente tipizzati, in parole povere ogni variabile od oggetto dichiarato all'interno del programma deve definire un tipo e lo deve rispettare (pena un errore di compilazione).

     

    Valore

    - Le variabili memorizzano direttamente gli oggetti, non è possibile aliasing

    Questi tipi rappresentano la stragrande maggioranza dei Tipi Primitivi (dati a sè stanti e non complessi, come un numero o un carattere), come System.Int16, System.Char, System.Boolean, System.DateTime.

    il valore del dato il quale viene allocato nella zona di memoria detta stack

    Reference

    - Le variabili memorizzano dei riferimenti a oggetti, l'assegnazione crea degli alias

    Questi tipi rappresentano tutti quei dati espressi tramite la dichiarazione di classi per descrivere oggetti complessi, essi vengono allocati nella memoria managed heap e non contengono direttamente il valore del dato, ma un puntatore ad una locazione di memoria dove è contenuto il valore vero e proprio, infine come è facile presumere questi possono assumere valore null.

     

     

    C#: struct, tipi di valore

     

    In c# è possibile creare i propri tipi valore usando struct

    I tipi valore possono essere allocati sullo stack, no aliasing

     

     

    Enum

     

    Simili a quelli di C/C++, un modo per definire delle costanti di tipo integrale

    internal enum Color {
    	Red,
    	Green,
    	Blue,
    }
    Color c=Color.green;

     

     

    Rilascio automatico delle risorse:

     

    using (var pippo=new StreamReader(@"c:\bla")) {
      //usa pippo...
    }

     

     

    Generici

     

    Simili a quelli Java (ma molto efficienti)

    Si possono mettere dei vincoli sugli argomenti tramite la clausola where

    public class C<T> where T : new() {
      public T Foo() {
      	return new T();
      }
    }

     

    Generici, vincoli

    • new(): l'argomento deve essere un tipo instanziabile, col costruttore di default
    • Atype: l'argomento deve essere sottotipo di AType, può essere il nome di un tipo del sistema o di un altro parametro del generico
    • struct: l'argomento deve essere un value type
    • class: l'argomento deve essere un tipo refernce (classe, interfaccia, delegate o array)

     

    Se si devono vincolare più argomenti, servono più clausole where

    class Test<T,U>
      where U : struct
        where T : E, new() { }

     

    Un parametro di tipo di un'interfaccia (o delegate) generica può essere:

    - out, può essere usato solo come tipo di ritorno.

    - in, può essere usato come tipo per i parametri e nei vincoli

    Esempi:

    interface IEnumerator<out T> {
      bool MoveNext();
      T Current {get;}
    }
    
    interface IComparer<in T> {
      int Compare(T left, T right);
    }
    
    delegate TResult Func<in TArg, out TResult> (Targ arg);
      

     

    Non ci sono funzioni/variabili globali (al più membri statici)

    Numero variabile di parametri: params T [] invece di T...

    Gli array possono essere "jagged" per sempio:

    int[][] myarray = new int[2][];
    	myarray[0]=new int[3];
    	myarray[0]=new int[9];
    Ma ci sono anche gli array bidimensionali:
    int[,] myArray = new int[,]{1,2,3},{4,5,6}}

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     Share


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...

Important Information

Terms of Use Privacy Policy Guidelines We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.