Εισαγωγή στο .ΝΕΤ Framework και
στη C#
Δημήτρης – Ηλίας Γκανάτσιος
Υπεύθυνος ακαδημαϊκών προγραμμάτων, Microsoft Hellas
v-digkan@microsoft.com | twitter.com/dgkanatsios | facebook.com/dgkanatsios
Version: 0.2.0.5, 11/3/2010
Περιεχόμενα
Τμήμα 1: Επισκόπηση του .NET Framework
Τμήμα 2: C#, μέρος 1: Basic Language Constructs
Types
Statements
Structures
Classes
Τμήμα 3: C#, μέρος 2
Delegates
Events
C# 3.0 και 4.0
Τμήμα 4: Base Class Library
Τμήμα 1: Επισκόπηση του .NET
Framework
Τι είναι το .ΝΕΤ
Common Language Runtime, Base
Class Library
Διαδικασία εκτέλεσης, Common
Language Infrastructure
Τι είναι το .ΝΕΤ Framework;
Πλατφόρμα στην οποία μπορούμε να
δημιουργήσουμε κάθε είδους εφαρμογές
Περιλαμβάνει μηχανισμούς και βιβλιοθήκες:
• Common language runtime (CLR)
• Class libraries (BCL ή FCL)
• Runtime Compiler (Jitter)
• Virtual Execution System (VES)
.NET Framework overview
Εκδόσεις του .ΝΕΤ
.NET 1.0 .NET 1.1 .NET 2.0
3.0
3.5
.NET 4
2002 2003 20102005-08
CLR 1.0 CLR 1.1 CLR 2.0 CLR 4
SP1
Το .NET Framework σε σχέση με το λειτουργικό
Τεχνικές σχεδίασης του .ΝΕΤ
• Διαλειτουργικότητα (Interoperability)
• Common Language Runtime
• Language Independence
• Base Class Library
• Simplified Deployment
• Security
• Portability
Common Language Infrastructure
– Το σύνολο της υποδομής του .ΝΕΤ Framework
– Αποτελείται από
• The Common Type System (CTS)
Σύνολο τύπων και λειτουργιών που είναι κοινοί σε όλες τις CTS-
συμβατές γλώσσες
• Metadata
Πληροφορίες για τους τύπους και τη δομή του εκτελέσιμου αρχείου ή
της βιβλιοθήκης
• Common Language Specification (CLS)
Βασικοί κανόνες οι οποίοι θα πρέπει να τηρούνται από οποιαδήποτε
γλώσσα κάνει target το CLI (ώστε να είναι .ΝΕΤ συμβατή)
• Virtual Execution System (VES)
Το VES φορτώνει και εκτελεί CLI-συμβατά προγράμματα και
βιβλιοθήκες.
– Είναι ανοικτό πρότυπο (ECMA-335 και ISO/IEC 23271)
– Από Ιούλιο 2009: C# και CLI υπό Community Promise
Common Type System
• Στόχοι:
– Να υπάρχει ένα framework που υποστηρίζει
cross-language integration, type safety και
εκτέλεση κώδικα με υψηλή απόδοση
– Η παροχή ενός αντικειμενοστρεφούς μοντέλου,
που υποστηρίζει την πλήρη υλοποίηση από
διάφορες γλώσσες προγραμματισμού
– Ο προσδιορισμός κανόνων που πρέπει να
ακολουθούν οι γλώσσες προγραμματισμού, ώστε
να είναι “interoperable”
Common Language Specification
• Οι CLS κανόνες προσδιορίζουν ένα υποσύνολο
του CTS
• Όλοι οι κανόνες του CTS εφαρμόζονται και στο
CLS, εκτός αν υπάρχει κάποιος «αυστηρότερος»
στο CLS
• Το CLS βοηθάει στο “language interoperability”
με το να προσδιορίζει χαρακτηριστικά που είναι
κοινά σε κάθε γλώσσα που κάνει target το CLR
• Example:
– UInt32 δεν είναι CLSCompliant
– C# case sensitive, Visual Basic όχι
Γλώσσες που υποστηρίζουν το πρότυπο
Common Language Runtime
• Just-in-time Compilation
• Memory management
• Garbage collection
• Thread management
• Exception handling
• Security
• Type safety
Διαδικασία
Εκτέλεσης
Application Domain
• Ένα application domain για το CLR είναι κάτι
παρεμφερές με το ό,τι είναι μία διεργασία
(process) για το λειτουργικό σύστημα
• Χρησιμοποιείται για να απομονώσει τις
εφαρμογές που εκτελούνται
– Ώστε η μία να μην επηρεάζει και να εκτελείται
ανεξάρτητα από την άλλη
Συλλογή απορριμμάτων 1/2
• Ο προγραμματιστής δημιουργεί νέα αντικείμενα και
πίνακες
– Τα πάντα δημιουργούνται και η μνήμη δεσμεύεται με ένα ειδικό
keyword.
• Το περιβάλλον εκτέλεσης του .NET παρακολουθεί
αυτόματα τη χρήση μνήμης
• Ο Garbage Collector αφαιρεί αυτόματα τα αχρησιμοποίητα
αντικείμενα
• Πιο αποτελεσματική διαχείριση μνήμης
• Ευκολία στη χρήση και “μηδενικές διαρροές”
Συλλογή απορριμάτων 2/2
A B C D E F
A C E
Τα B,D βγαίνουνε out of scope, με
το F να «κρέμεται» από το B
Κλήση της GC.Collect()
NextObjectPointer
…
…
NextObjectPointer
Τι μπορούμε να προγραμματίσουμε;
• Εφαρμογές κονσόλας
• Εφαρμογές για Windows (διεπαφή χρήστη σε Windows Forms)
• Εφαρμογές για Windows με το Windows Presentation Foundation (WPF)
• ASP.NET εφαρμογές που εκτελούνται σε Web Servers
• Web services
• Windows services
• Service-oriented applications using Windows Communication Foundation (WCF)
• Workflow-enabled applications using Windows Workflow Foundation (WF)
• Silverlight Applications
• Mobile Applications (Compact Framework)
• Embedded Applications (Micro Framework)
• Office Applications (VSTO)
• SharePoint Applications
• XBOX 360 Games, PC Games, Zune Games (XNA)
• Windows 7 (με το Windows 7 API Code Pack) – συμπεριλαμβάνεται Sensor και Location Platform
• Visual Studio Tools for Office
• Microsoft Dynamics CRM
• Οτιδήποτε έχει API σε .ΝΕΤ!
Τι βιβλιοθήκες μπορούμε να
χρησιμοποιήσουμε;
• Base Class Library (BCL)
– Χιλιάδες έτοιμες κλάσεις για το προγράμματά μας
– Προσβάσιμες σε κάθε σύστημα που έχει εγκατεστημένο το .NET
Framework
– Διαθέσιμες από εύκολα αναγνωρίσιμους χώρους ονομάτων, π.χ.
System.Data.SqlClient.SqlConnection
System.Windows.Forms.Form
System.Net.Sockets.TcpClient
System.Xml.XmlReader
• Χιλιάδες code samples και open source projects που παρέχονται
δωρεάν στο διαδίκτυο
• www.codeplex.com
• code.msdn.microsoft.com
• blogs.msdn.com
• weblogs.asp.net
Ωφέλη του .NET Framework
• Many languages, One Intermediate Language,
Many platforms
• Αποχαιρετήστε τα memory leaks (Garbage
Collector)
• Optimization per CPU / platform
• Ένα περιβάλλον προγραμματισμού για πολλών
ειδών εφαρμογές
• Ιδανικό μοντέλο ασφάλειας
• Deployment
Γιατί C# ?
Μια component-oriented γλώσσα
Επαναχρησιμοποιήσιμες βιβλιοθήκες
Εγγενής υποστήριξη για
Namespaces
Versioning
Attribute-driven ανάπτυξη
Η δύναμη της C/C++ με την ευκολία της Visual Basic
Ελάχιστη καμπύλη εκμάθησης για όλους
Πιο σαφής από την C++
Πιο δομημένη από τη Visual Basic
Περισσότερες δυνατότητες από τη Java
Δυνατότητες functional programming (όπως η Haskell, η Scheme
κ.λ.π.)
Δυνατότητες dynamic programming (έκδοση 4)
Τμήμα 2: C# - The Language
Μορφή και Δομή
Δεν υπάρχουν header files
Μεταγλώττιση υπό συνθήκη – αλλά όχι macros
Μεταγλώττιση σε .NET assembly (είτε .exe είτε .dll)
Μόνο object oriented κώδικα
Main() entry point του προγράμματος (μόνο για
εκτελέσιμα αρχεία)
Hello World
public class HelloWorld
{
public static void Main()
{
System.Console.WriteLine("Hello World!");
}
}
Visual Studio
• IDE (Integrated Development Environment)
• Γλώσσες: C++, C#, F#, Visual Basic κ.α.
• Δωρεάν πρόσβαση
– Για φοιτητές: MSDNAA – www.dreamspark.com
– Για startups: www.bizspark.com
– Για web agencies: www.websitespark.com
• Express editions: www.microsoft.com/express
• Web Platform Installer:
www.microsoft.com/web
Σύστημα τύπων
• Εγγενής πρόσβασή στο σύστημα τύπων του
.NET
• Βασικές έννοιες:
–Τα πάντα είναι objects
• Τα πάντα κληρονομούν το System.Object
–Ξεκάθαρη διάκριση ανάμεσα στους τύπους τιμής
και αναφοράς
• Με τιμή: απλοί τύποι, enums, structs
• Με αναφορά: Interfaces, Κλάσεις, Πίνακες
Απλοί Τύποι
• Τύποι Ακεραίων
– byte, sbyte (8bit), short, ushort (16bit)
– int, uint (32bit), long, ulong (64bit)
• Τύποι κινητής υποδιαστολής (IEEE)
– float (ακρίβεια 7 ψηφίων)
– double (ακρίβεια 15–16 ψηφίων)
• Exact Numeric Type
– decimal (28 σημαντικά ψηφία)
• Τύποι Χαρακτήρων
– char (ένας χαρακτήρας)
– string (πλούσια λειτουργικότητα, τύπος αναφοράς)
• Τύποι Boolean
bool (ξεχωριστός τύπος, διαφορετικός από τον int)
Value Types και Reference Types
• Κατά κανόνα, τα value types είναι οι απλοί τύποι
(int, double, byte κ.λ.π.) και οι δομές (struct)
– Το System.String ενώ είναι reference type, το χρησιμοποιούμε σαν
value type
• Reference types είναι οι υπόλοιποι τύποι (όλες οι
κλάσεις, events, delegates κ.λ.π.)
• Αποθήκευση στη μνήμη του προγράμματος
– τα value types (όταν δηλώνονται μέσα σε μια μέθοδο)
αποθηκεύονται στη στοίβα (stack)
– τα reference types (μαζί με τα value types τα οποία μπορεί
να περιέχουν) αποθηκεύονται στο σωρό (heap)
‘Πέρασμα’ μεταβλητών σε μεθόδους
• Πέρασμα τιμών χωρίς keyword (κατ’αξία)
μη διατηρήσιμη αλλαγή τιμής
• Πέρασμα τιμών με το ref keyword
(κατ’αναφορά)
επιτρέπεται αλλαγή τιμής
• Πέρασμα τιμών με το out keyword (output)
επιβάλλεται ανάθεση τιμής
Δηλώσεις (Statements)
Έλεγχος ροής και επαναλήψεις
if (<bool expr>) { ... } else { ... };
switch(<var>) { case <const>: ...; };
while (<bool expr>) { ... };
for (<init>;<bool test>;<modify>) { ... };
do { ... } while (<bool expr>);
Απαριθμητοί Τύποι (Enums)
Χρησιμοποιούνται στοιχεία με όνομα αντί για αριθμητικές
επιλογές
Ισχυρός τύπος, όχι αυτόματη μετατροπή σε int
Καλύτερο το "Color.Blue" από μια αριθμητική έκφραση
Πιο κατανοητό, ευκολότερη συντήρηση
Εξίσου ελαφρύ με το απλό int (αν δεν δηλωθεί άλλος τύπος στο enum)
Παράδειγμα:
enum Color
{
Red,
Green,
Blue,
Yellow
};
Πίνακες (Arrays)
Zero based, type bound
Βασίζονται στην .NET κλαση System.Array
Δηλώνονται με τύπο και μορφή, αλλά χωρίς όρια
int[] SingleDim;
int[,] TwoDim;
int [][] Jagged;
Δημιουργούνται με χρήση του new με όρια ή
initializers
SingleDim = new int[20];
TwoDim = new int[,]{{1,2,3},{4,5,6}};
Jagged = new int[1][];
Jagged[0] = new int[]{1,2,3};
Τελεστές (Operators)
Σαν τη C:
Λογικοί/Συνθήκης: && || ^
Αριθμητικοί: * / + - % << >>
Σχεσιακοί: == != < > >= <=
Όχι ακριβώς σαν τη C:
Για bool: & και | είναι λογικοί με πλήρη απαρίθμηση
Για ακεραίους: & και | υλοποιούν δυαδικό AND/OR
Καθόλου σαν τη C:
is Ελέγχει τον run-time τύπο
as Μετατρέπει μια τιμή σε άλλο τύπο
typeof Ανακτά τον run-time τύπο
Structures
• Είναι value Types
• Ιδανικά για μικρούς τύπους δεδομένων
• Μπορούν να περιέχουν μεθόδους
• Τα fields μπορεί να είναι public, private ή internal
• Δεν μπορούν να κάνουν inherit κλάση
• Μπορούν να κάνουν implement interface
struct MyStruct
{
public int i;
private string s;
public void WriteToConsole()
{
Console.WriteLine("I am a struct");
}
}
Κλάσεις
Υλοποίηση κώδικα και δεδομένων
Αναπαριστά μια σημασιολογική
ενότητα
Μπορεί να υλοποιεί interfaces
Μπορεί να κληρονομεί από μία
βασική κλάση (base class)
Οι κλάσεις περιέχουν:
Πεδία (Fields): μεταβλητές μελών
Ιδιότητες (Properties): τιμές στις οποίες γίνεται
πρόσβαση με ζευγάρια μεθόδων get/set
Μέθοδοι (Methods): λειτουργικότητα για το
αντικείμενο ή την κλάση
Άλλα: events, indexers, delegates
public class Person :
IPersonAge
{
private int YOB;
public Person()
{
}
public int YearOfBirth
{
get { return YOB; }
set { YOB = value; }
}
public int GetAgeToday()
{
return Today()-
YearOfBirth ;
}
}
Ιδιότητες (Properties)
Ευκολία υλοποίησης μεθόδων
Χρησιμοποιούμε properties για:
Υλοποίηση read-only μελών
(παραλείποντας το set)
Επικύρωση κατά την ανάθεση
Παράγωγες ή σύνθετες τιμές
Έκθεση τιμών στα interfaces
Παράδειγμα: string Name
{
get { return name; }
set { name = value; }
}
Χώροι Ονομάτων (Namespaces)
• Κάθε ορισμός πρέπει να περιέχεται σε ένα namespace
– Αποφεύγεται η σύγκρουση ονομάτων
– Καλύτερη οργάνωση
– Οι βιβλιοθήκες γίνονται ευκολότερες στην
κατανόηση
• Μπορούν να εμφωλιάζονται
• Ομάδες κλάσεων και τύπων κατά χρησιμότητα
• Δηλώνονται με τη λέξη-κλειδί namespace
• Συντόμευση για χρήση σε κώδικα, με using
Iteration με χρήση της foreach
List<string> stringList = new List<string>();
stringList.Add("one");
stringList.Add("two");
stringList.Add("three");
stringList.Add("four");
//stringList.Add(5); won’t compile, as 5 is not a string
foreach(string s in stringList)
if(s.Contains("e"))
Console.WriteLine(s);
Χρησιμοποιείται σε arrays και collections.
Προσοχή: Μέσα από την foreach, ΔΕΝ πειράζουμε την collection
(π.χ. Δεν κάνουμε κάποιο add ή remove, καθώς έτσι «σπάει» ο Enumerator)
Κληρονομικότητα – Πολυμορφισμός 1
• Η C# υποστηρίζει κληρονομικότητα
• Κάθε κλάση μπορεί να κληρονομήσει
χαρακτηριστικά μόνο μίας κλάσης
• Πολλαπλή κληρονομικότητα δεν
υποστηρίζεται (παρά μόνο (κάπως) με τα
Interfaces)
• Χρήση των λέξεων abstract, sealed, virtual,
new
Κληρονομικότητα – Πολυμορφισμός 2
class Parent
{
public void A(){...}; public virtual void B(){...};
}
class Child : Parent
{
public new void A(){...}; //A() not declared as virtual on Parent
public override void B(){...}; //B() declared as virtual on Parent
}
public static void Main()
{
Child c = new Child();
c.A(); // Child::A()
c.B(); // Child::B()
Parent p = c as Parent;
p.A(); // Parent::A()
p.B(); // Child::B()
}
Προστασία Πρόσβασης
Υιοθετεί το μοντέλο της C++
public  Όλοι μπορούν να καλέσουν ή να έχουν πρόσβαση
protected  Μόνο τα μέλη έχουν πρόσβαση
private  Μόνο τα μέλη και μόνο αυτής της κλάσης
Αλλά και το επεκτείνει
Modifiers για κλάσεις
sealed  Δεν μπορεί να χρησιμοποιηθεί σαν βασική κλάση
internal  Public πρόσβαση μόνο μέσα στην assembly
protected internal  Protected στην assembly (σημαίνει protected OR
internal)
abstract  δεν μπορεί να γίνει instantiate, αλλά μπορεί μόνο να
κληρονομηθεί
Abstract classes - Interfaces
• Abstract classes : υποχρεωτικά κληρονομούνται
– Μπορούν να έχουν υλοποιήσεις μεθόδων, ή σκέτες δηλώσεις
– Μπορούν να έχουν fields
– Αν θέλουμε μια κλάση να *μην* μπορεί να κληρονομηθεί, τότε τη
χαρακτηρίζουμε ως sealed
• Interfaces: Συμβόλαια δήλωσης σημασιολογίας μεταξύ δύο
μερών
– Μπορούν να γίνουν implement από structures ή classes
– Δεν έχουν υλοποιήσεις μεθόδων, αλλά μόνο δηλώσεις
– Μπορούν να έχουν δηλώσεις από properties
• Παράδειγμα:
interface IPersonAge
{
int YearOfBirth {get; set;}
int GetAgeToday();
}
Οι λέξεις is και as
• is: έλεγχος για τον τύπο ενός αντικειμένου
if(objectInstance is MyClass)
• as: αποτρέπει InvalidCastException από μη επιτρεπτό
cast
αντί π.χ. για
(MyClass)objectInstance
το οποίο μπορεί να επιφέρει Exception,
χρησιμοποιούμε το
objectInstance2 = objectInstance as MyClass
– Αν το cast είναι επιτρεπτό, επιστρέφει objectInstance
– Ειδάλλως, επιστρέφει null
Η λέξη static
• Όταν χαρακτηρίσουμε ένα property ή μεταβλητή
μιας κλάσης με τη λέξη static, τότε η τιμή της
είναι η ίδια για κάθε instance της κλάσης
• Όταν χαρακτηρίσουμε μια κλάση με τη λέξη
static, τότε δεν μπορούμε να δημιουργήσουμε
instance αυτής της κλάσης
– Χρήσιμο για καταστάσεις που χρειαζόμαστε ένα και
μόνο instance μιας κλάσης
– Οι static κλάσεις έχουνε αποκλειστικά static μέλη
Generics
• Παρόμοια με τα templates της C++
• Επιτρέπουν type safety
• Εύκολος τρόπος για πιο «γενικά» αντικείμενα
• Π.χ. εκτύπωση των αντικειμένων ενός πίνακα
void Print<T>(T[] myArray)
{
foreach(T myObject in myArray)
Console.WriteLine(myObject.ToString());
}
Περισσότερα για generics:
http://msdn2.microsoft.com/en-us/library/ms379564(VS.80).aspx
Iterators
• Εισήχθησαν στην C# 2.0
• Είναι μία μέθοδος, get accessor που επιτρέπει
την χρήση επανάληψης (for, foreach, while, do
while) στην κλάση ή το struct χωρίς να χρειάζεται
να υλοποιηθεί το interface IEnumerable
• Αποτελείται από ένα κομμάτι κώδικα που
«επιστρέφει» ταξινομημένη σειρά τιμών ίδιου
τύπου
• Χρησιμοποιεί το yield return
Παράδειγμα
public class SampleCollection
{
public int[] items = new int[5] { 5, 4, 7, 9, 3 };
}
public IEnumerable><int> BuildCollection()
{
for (int i = 0; i < items.Length; i++) //το πρόγραμμα θα γυρίσει εδώ μετά την
{ //εκτέλεση της yield
yield return items[i];
}
}
}
class MainClass
{
static void Main()
{
SampleCollection col = new SampleCollection();
foreach (int i in col.BuildCollection())
{
Console.WriteLine(i);
}
}
}
Nullable Types
• Με την χρήση των nullable types, μπορούμε να
καταχωρήσουμε την τιμή null σε κάποιον value type
– Π.χ.
int? x; //ίδιο με το Nullable<int> x;
x = null;
– Μπορούμε να ελέγξουμε για ύπαρξη τιμής με το
if(x.HasValue)
– Μπορούμε να πάρουμε την τιμή (αφού ελέγξουμε για
HasValue) με
int y = x.Value;
• Χρήσιμα όταν περιμένουμε είτε «κανονική», είτε null τιμή
από κάπου (π.χ. βάση δεδομένων με nullable πεδίο)
Αντιπρόσωποι (Delegates)
• Κάτι σαν τους δείκτες σε συναρτήσεις (C/C++)
• Ισχυροί τύποι, όχι σύγχυση στο type-casting ή σφάλματα.
• Η δήλωση δημιουργεί μια typed method signature:
– delegate void Clicked(Element e, Point p);
• Ο πραγματικός αντιπρόσωπος είναι ένα στιγμιότυπο αυτού του
τύπου
– Clicked MyClickHandler
= new Clicked(obj.OnButtonClick);
• Το όρισμα περνιέται στον constructor του αντιπροσώπου:
– Αναφορά στο στιγμιότυπο του αντικειμένου και στη
μέθοδο.
– Η μέθοδος πρέπει να έχει την ίδια ακριβώς
υπογραφή
• void OnButtonClick(Element e, Point p) { ... };
Συμβάντα (Events)
• Μοντέλο συμβάντων ενσωματωμένο στη γλώσσα
• Όλη η διαχείριση γίνεται από τη C#
• Τα events δηλώνονται με έναν τύπο delegate
• Η δήλωση δημιουργεί μια πηγή συμβάντος για να γίνει
bind
– event Clicked OnClicked;
– Τα event sinks γίνονται bind στην πηγή του συμβάντος με
delegates
Clicked MyClickHandler = new Clicked(obj.OnButtonClick);
– Προσθήκη handler:
• btnAction.OnClicked += MyClickHandler;
– Απαλοιφή handler:
• btnAction.OnClicked -= MyClickHandler;
• Η πηγή του συμβάντος “πυροδοτεί” events με μια απλή
κλήση
– if(OnClicked != null) OnClicked(this,PointerLocation);
Χειρισμός Εξαιρέσεων
• Παρόμοιος με τη C++
• Μοντέλο SEH (Structured Exception Handling)
• Διαβάζεται ως εξής:
– try να τρέξεις αυτό τον κώδικα...
– ... αν προκύψει σφάλμα, catch ό,τι μπορείς να χειριστείς...
– ...finally άφησε με να τελειώσω το cleanup με το χέρι
• Παράδειγμα:
try {
//... run code
}
catch(SomeException e) {
//... handle
}
finally {
//...end gracefully
}
Partial Classes
Partial classes: Η υλοποίηση μιας κλάσης μπορεί να ‘σπάσει’ σε πολλά
αρχεία
– Βοηθάει στην ανάπτυξη λογισμικού από ομάδες
προγραμματιστών
– Χρησιμοποιούμε τη λέξη partial στον ορισμό της κλάσης
– Βοηθάει στο διαχωρισμό κώδικα διαφορετικής χρηστικότητας
• Παράδειγμα: Σε μια Windows Forms εφαρμογή, έστω ότι
δημιουργούμε μια καινούρια Form, ονόματι MyForm. Τότε:
– Ο κώδικας που δημιουργείται από τον Visual Studio
designer της φόρμας (με drag-drop κ.λ.π.) τοποθετείται
στο αρχείο MyForm.Designer.cs
– Ο κώδικας που γράφουμε εμείς τοποθετείται στο
MyForm.cs
Anonymous methods
• Anonymous methods : in-line κατασκευή μιας
συνάρτησης η οποία προορίζεται για χρήση μέσω
delegate
– Ελάττωση του απαιτούμενου κώδικα για «μικρές»
συναρτήσεις
Τμήμα 3: C# 3.0
Η μεγαλύτερη καινοτομία της C# 3.0
Μεγαλύτερη καινοτομία: επερωτήσεις στα
δεδομένα, οτιδήποτε είδους
var query =
from p in employees
where p.Salary > 33000m
orderby p.Name, p.StartDate descending
select p.Name;
Anonymous types
Σαν ένας κανονικός τύπος που ζει στο CLR
var v = new { Amount = 108, Message = "Hello" };
Extension methods
• Επιτρέπεται να προστεθούν μέθοδοι σε
υπάρχοντες τύπους χωρίς να δημιουργούμε
έναν νέο derived τύπο
• Καλούνται πολύ εύκολα (just static methods
underneath)
• Method chaining
Παράδειγμα
• string x = "some string
value";
string y =
Utility.Reverse(x);
• string x = "some string
value";
string y = x.Reverse();
public static class Utility
{
public static string
Reverse(this string input)
{
char[] chars =
input.ToCharArray();
Array.Reverse(chars);
return new String(chars);
}
}
Lambda expressions
• Σαν anonymous method αλλά μικρότερο
• Χρησιμοποιεί τον lambda operator => που
διαβάζεται goes to δηλαδή «συνεπάγεται»
• Αριστερά έχουμε παραμέτρους εισόδου και
δεξιά την έκφραση ή το κομμάτι κώδικα.
• Shorthands
– Parameter type inference
– Brace removal (single expression/statement)
– Bracket removal (single parameter)
• Expression Trees
Παράδειγμα
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };
foreach (int i in source.Where(x => x > 5))
Console.WriteLine(i);
Παράδειγμα (C# 1.0)
// Δήλωση delegate
public delegate int ChangeInt(int x);
// Μία μέθοδος στην οποία μπορεί να δείξει η από πάνω μεταβλητή
static public int DoubleIt(int x)
{
return x * 2;
}
// Δημιουργία στιγμιοτύπου
ChangeInt myDelegate = new ChangeInt(DelegateSample.DoubleIt);
Console.WriteLine("{0}", myDelegate(5));
Παράδειγμα (C# 2.0)
ChangeInt myDelegate = new ChangeInt(
delegate(int x)
{
return x * 2;
}
);
Console.WriteLine("{0}", myDelegate(5));
Παράδειγμα (C# 3.0)
ChangeInt myDelegate = x => x * 2;
Console.WriteLine("{0}", myDelegate(5));
LINQ
Χαρακτηριστικά
• Δυνατότητα επερωτήσεων
μέσα στη γλώσσα
• Περιέχει Standard Query
Operations
– Select
– Where
– Join
– Take/Skip
– Group By
• Providers
C# 4.0
dynamic keyword
optional parameters
Τμήμα 4: Base Class Libraries
Dictionaries
Τα Dictionaries είναι δομές δεδομένων που αποθηκεύουν ζευγάρια key/values σε θέσεις
που λέγονται KeyValuePair. Το κυριότερο πλεονέκτημα των Dictionaries είναι ότι η
αναζήτηση είναι πολύ γρήγορη γιατί η «σκληρή» δουλειά γίνεται κατά τη φάση της
αποθήκευσης. Στην ουσία, ένα μοναδικό κλειδί αποκτάται για την αποθήκευση των τιμών
στα KeyValuePair.
Ένας συνηθισμένος κώδικας που χρησιμοποιεί Dictionaries περιλαμβάνει:
Dictionary<string, string> aDict = new Dictionary<string, string>();
aDict.Add("Sunday", "Dimitris"); // (key,value) pair
aDict["Monday"] = "Gkanatsios"; // aDict ]=value;
foreach (KeyValuePair<string, string> entry in aDict)
Console.Write("Key={0}, Value={1}n", entry.Key, entry.Value);
Arrays
Υπάρχουν δύο τύποι arrays στο .NET:
Array είναι μια class που προέρχεται κατεθευθείαν από το System.Object. Αυτή η class
μπορεί να χρησιμοποιηθεί για να υλοποιήσετε στατικές (συγκεκριμένου μεγέθους) arrays
για την αποθήκευση πρωτόγονων τύπων. Ένα element (στοιχείο) είναι μια τιμή μέσα στην
Array. Το length είναι ο συνολικός αριθμός των elements μέσα στο array. Το rank του Array
είναι ο αριθμός των διαστάσεων του.
Το κάτω όριο μιας διάστασης ενός Array είναι ο πρώτος αριθμοδείκτης εκείνης της
διάστασης του Array. Μια πολυδιάστατη Array μπορεί να έχει διαφορετικά όρια για κάθε
διάσταση.
Τα Type objects παρέχουν πληροφορίες για την δήλωση των array type. Τα Array objects
με τον ίδιο Array type μοιράζονται το ίδιο Type object.
Το Array έχει 6 ιδιότητες (IsFixedSize, IsReadOnly, IsSynchronized,
Length, Rank, SyncRoot), 22 μεθόδους ( BinarySearch, Clear, Copy, Equals,
GetValue, GetLength, IndexOf, Initialize, Reverse, SetValue, Sort, ToString,
Finalize κ.α.). Η class επίσης εφαρμόζει διάφορες μεθόδους της IList, που περιλαμβάνουν
τα ( Add, Clear, Contains, IndexOf, Insert, Remove, RemoveAt ).
ArrayList
H ArrayList είναι μια class που προέρχεται από το System.Collections. Αυτή η class δεν έχει
καμία σχέση με τη class System.Object.Array. Η δήλωση της class είναι:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
Το κείμενο δείχνει τις εξής ιδιότητες της class:
ArrayList aList = new ArrayList ();
aList.Add ("John"); aList.Add ("Paul"); aList.Add ("George");
Για την ανάκτηση ενός αντικειμένου από την ArrayList, χρησιμοποιήστε μια αριθμοδότηση
βασισμένη στο 0:
int i = (int) list[0];
Για την ανάθεση ενός αντικειμένου στην ArrayList, κάνουμε το εξής:
list[0] = 999;
Η ιδιότητα Count αποκαλύπτει πόσα αντικείμενα περιέχει μια ArrayList.
for (int i=0; i<list.Count; i++) Console.WriteLine ( list[i] );
Μπορείτε να ανατρέξετε την ArrayList με το foreach:
foreach (int i in list) Console.WriteLine (i);
List<T>
• Generic μορφή του ArrayList
List<int> list = new List<int>();
for (int i = 0; i < 100; i++)
list.Add(i * 2);
list.Add("string"); //compilation error
Regular Expressions
Το RegEx είναι μια class προερχόμενη από το name space System.Text.RegularExpressions.
Τα RegEx αντικείμενα μπορούν να χρησιμοποιηθούν για:
• Να χωριστούν strings σε substrings, χρησιμοποιώντας τα RegExps για να αναγνωριστούν τα
διαχωριστικά.
• Να ψάξετε για substrings μέσα στα strings, χρησιμοποιώντας τις RegEx εκφράσεις για να
αναζητήσετε σχέδια (patterns).
• Να κάνετε λειτουργίες Αναζήτησης-Αντικατάστασης χρησιμοποιώντας το RegEx για να
αναγνωρίσετε αυτά που πρέπει να αντικατασταθούν στο κείμενο.
• Ανάλυση αρχείων HTML.
Όταν δημιουργούνται RegEx objects, η έκφραση που περιγράφει το pattern χρησιμοποιείται ως
ένα όρισμα στο constructor:
using System.Text.RegularExpressions;
Regex regex = new Regex ("[a-z]");
Regex regex = new Regex ("[a-z]", RegexOptions.IgnoreCase);
Regex regex = new Regex (@"");
string[] parts = regex.Split (@"c:inetpubwwwrootwintellect");
foreach (string part in parts) Console.WriteLine (part);
c:
inetpub
wwwroot
wintellect
Οποιοδήποτε μικρό
γράμμα της αλφαβήτας
Επιστρέφει τα substrings μέσα στο string
διαχωρισμένα από το όρισμα μέσα στο
RegExp
Χρήση του RegEx, μέρος 2
Για την ανάλυση ενός αρχείου html, με, π.χ.,
<b>Every</b>good<h3>boy</h3>does<b>fine</b>
Regex regex = new Regex ("<[^>]*>");
string[] parts =
regex.Split ("<b>Every</b>good<h3>boy</h3>does<b>fine</b>");
foreach (string part in parts) Console.WriteLine (part);
Αυτός ο κώδικας παράγει:
“Every good boy does fine” (μια λέξη ανά γραμμή).
Παρατηρήστε ότι “<[^>]*>” σημαίνει: οτιδήποτε ξεκινά με “<” ακολουθόμενο από οποιουσδήποτε
χαρακτήρες εκτός από το “>”, ακολουθόμενο από το “>”.
To Regex περιλαμβάνει 3 μεθόδους για αναζήτηση substrings μέσα σε strings: Match, Matches, και IsMatch.
Με αυτά, είναι αρκετά εύκολο να γράψει κανείς grep-like. Το πρόγραμμα μπορεί να χρησιμοποιηθεί για να
κάνει οποιαδήποτε greps, όπως π.χ.
NetGrep index.html “<a[^>]*>”
Η παραπάνω εντολή θα εμφάνιζε τις γραμμές μέσα στις οποίες εμφανίζεται το <a> στο αρχείο index.html.
Παρόμοια, η εντολή
NetGrep file1.txt “d{2,}”
Θα εμφάνιζε τις γραμμές που περιλαμβάνουν ακέραιους αριθμούς με δύο ή περισσότερα ψηφία μέσα στο
file1.txt, κ.τ.λ.
Χρήση του RegEx, μέρος 3
using System;
using System.IO;
using System.Text.RegularExpressions;
class MyApp {
static void Main (string[] args) {
if (args.Length < 2) {
Console.WriteLine ("Syntax: NETGREP filename expression");
return;
}
StreamReader reader = null;
int linenum = 1;
try {
// Initialize a Regex object with the regular expression
// entered on the command line
Regex regex = Regex (args[1], RegexOptions.IgnoreCase);
// Iterate through the file a line at a time and display all lines that contain a
pattern matching the regular expression
reader = new StreamReader (args[0]);
for (string line = reader.ReadLine (); line != null; line = reader.ReadLine (),
linenum++) {
if (regex.IsMatch (line)) Console.WriteLine ("{0:D5}: {1}", linenum, line);
}
}
catch (Exception e) {
Console.WriteLine (e.Message);
}
finally {
if (reader != null) reader.Close ();
}
}
}
Internet Classes
Αυτές οι classes υπάρχουν στο name space System.Net. Υπάρχουν 36 classes, 5 interfaces,
ένα delegate, και 4 enumerations.
Οι πιο σημαντικές classes είναι: Cookie, CookieCollection,
Dns, HttpWebRequest, HttpWebResponse, HttpVersion,
HttpWebRequest, HttpWebResponse, IPAddress, IPEndPoint,
IPHostEntry, NetworkCredential, ProtocolViolationException,
SocketAddress, WebClient, WebException, WebPermission,
WebProxy, WebRequest, WebResponse και άλλα.
Ο επόμενος κώδικας δείχνει μόνο πως να χρησιμοποιήσετε το WebRequest και
WebResponse στο LinkList.cs, που παίρνει ένα URL ως όρισμα.
Η εφαρμογή πάει στο URL και εμφανίζει τις γραμμές που περιλαμβάνουν αναφορές σε
άλλα websites, π.χ. Υπερσυνδέσμους. Ο κώδικας είναι αρκετά απλός.
System.Net.Mail
Είναι αρκετά εύκολο να στείλετε e-mail από ένα .NET Framework πρόγραμμα (αρκεί να
έχετε τις σωστές άδειες). Το System.Net.Mail παρέχει ένα managed interface για το SMTP.
Οι κυριότερες classes είναι:
1. MailMessage, που αναπαριστά τα μηνύματα emails;
2. MailAttachment, που αναπαριστά τα συννημένα αρχεία;
3. SmtpClient, που χειρίζεται την υπηρεσία μηνυμάτων SMTP του συστήματος.
Αυτά είναι τα βήματα για να σταλθούν emails με το System.Web.Mail:
MailMessage message = new MailMessage();
message.From = new MailAddress("v-digkan@microsoft.com");
message.To.Add(new MailAddress("dt008@hotmail.com"));
message.Subject = "test subject";
message.Body = "test body...";
SmtpClient cl = new SmtpClient();
cl.Host = "mail.gkanatsios.com";
cl.Send(message);
Data Access
• Πληθώρα από τεχνολογίες Βάσεων Δεδομένων (ODBC, DAO, RDO, ADO, και OLEDB).
• Συνέπραξαν στην πορεία προς το ADO.NET, το οποίο εφαρμόζεται στο System.Data
namespace.
• Το ADO.NET έχει δύο βασικούς τύπους classes, αυτούς που είναι βελτιστοποιημένοι
για τον Microsoft SQL Server και όλους τους άλλους που περιλαμβάνονται στο OleDB,
το οποίο δεν είναι γρήγορο αλλά είναι πιο γενικό.
Οι base classes είναι:
• Connection (OleDbConnection, SqlConnection)
• Command (SqlCommand and OleDbCommand)
• DataReader (OleDbDataReader, SqlDataReader)
• DataSet
• DataAdapter (SqlDataAdapter, OleDbDataAdapter)
• Exception (SqlException, OleDbException
Data Readers, παράδειγμα
SqlConnection connection = new
SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
connection.Open();
SqlCommand command = new SqlCommand("select * from titles", connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
Console.WriteLine(reader.GetString(1));
connection.Close();
Για απλότητα, ο παραπάνω κώδικας δε διαχειρίζεται τυχόν σφάλματα.
Data Readers, μέρος 2
SqlConnection connection = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
try
{
connection.Open();
SqlCommand command = new SqlCommand("select * from titles", connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
Console.WriteLine(reader.GetString(1));
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
}
finally
{
connection.Close();
}
Παρόμοιος κώδικας μπορεί να χρησιμοποιηθεί για οποιοδήποτε άλλον OleDb data
provider, απλά αντικαθιστώντας τους SQL types με τους αντίστοιχους OleDB types.
Updating Data
Όπως το όνομα υπονοεί, οι Data Readers μπορούν μόνο να πάρουν δεδομένα από μια πηγή
δεδομένων. Αν χρειάζονται λειτουργίες εγγραφής, τότε χρειάζεται ένα command object.
SqlConnection connection = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
try
{
connection.Open();
string sqlcmd = "insert into titles (title_id, title, type, pub_id, price, advance, royalty, ytd_sales, notes, pubdate)
values ('BU1001', 'Programming Microsoft.NET', 'Business', '1389', NULL, NULL, NULL, NULL, 'Learn to program
Microsoft.NET', 'Jan 01 2002')";
SqlCommand command = new SqlCommand(sqlcmd, connection);
command.ExecuteNonQuery();
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
}
finally
{
connection.Close();
}
DataSets και DataAdapters
Το DataSet είναι η αναπαράσταση μιας βάσης δεδομένων αποθηκευμένη στη μνήμη και
μπορεί να περιέχει πολλαπλούς πίνακες δεδομένων με constraints και relationships. Τα
DataSets χρησιμοποιούνται μαζί με τους DataAdapters για τη διευκόλυνση της πρόσβασης
ανάγνωσης/γραφής στις βάσεις δεδομένων.
SqlDataAdapter adapter = new SqlDataAdapter("select * from
titles","server=localhost;uid=sa;pwd=;database=pubs");
DataSet ds = new DataSet();
adapter.Fill(ds);
foreach (DataRow row in ds.Tables[0].Rows)
Console.WriteLine(row[1]);
Παρατηρήστε τη χρήση του foreach, η οποία σημαίνει ότι το DataSet έχει collections από
στήλες και γραμμές.
LINQ To SQL
• Το Linq To SQL είναι
ένας εξελιγμένος O/R
Mapper που μας
επιτρέπει εύκολη
πρόσβαση σε δεδομένα
από SQL Server.
• Το Visual Studio
ενσωματώνει έναν
εύχρηστο designer.
Παράδειγμα
using
(NorthwindDataContext context = new NorthwindDataContext())
{
var customers = from c in context.Customers
where(c.ContactName.Contains(
textBoxCustomerName.Text.Trim()) &&
c.CompanyName.Contains(textBoxCompanyName.Text.Trim()))
select c;
gridViewCustomers.DataSource = customers;
gridViewCustomers.DataBind();
}
LINQ To XML
• Με το LINQ To XML μπορούμε εύκολα να
επεξεργαστούμε αρχεία XML
– Ακόμα και HTML, αν είναι valid!
• Ενώ υπάρχει στο .ΝΕΤ δυνατότητα για χρήση
XML DOM αλλά και το XQuery, το LINQ To
XML είναι πιο φιλικό στον προγραμματιστή
Ένα αρχείο XML
<?xml version="1.0" encoding="utf-8" ?>
<Tutorials>
<Tutorial>
<Author>The Reddest</Author>
<Title>
Creating an XP Style WPF Button with Silverlight
</Title>
<Date>2/20/2008</Date>
</Tutorial>
<Tutorial>
<Author>The Fattest</Author>
<Title>
Flex And Yahoo Maps
</Title>
<Date>2/12/2007</Date>
</Tutorial>
<Tutorial>
<Author>The Tallest</Author>
<Title>
WPF Tutorial - Creating A Custom Panel Control
</Title>
<Date>2/18/2008</Date>
</Tutorial>
</Tutorials>
Parsing με LINQ To XML
XDocument xmlDoc = XDocument.Load("TestFile.xml");
var tutorials = from tutorial in
xmlDoc.Descendants("Tutorial")
select new
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = tutorial.Element("Date").Value,
};
Reflection
Οι Managed εφαρμογές αναπτύσσονται σε assemblies που περιέχουν πολλαπλά αρχεία
και μπορούν να περιέχουν πολλαπλά modules με managed ή unmanaged κώδικα.
Τα managed modules περιέχουν metadata (~ επιπλέον, συνήθως περιγραφικές,
πληροφορίες) που περιγράφουν το περιεχόμενο τους και τις δομές δεδομένων μέσα σε
κάτι που καλείται «manifest».
Αυτές οι πληροφορίες μπορούν να ανακτηθούν χρησιμοποιώντας το ILDASM, ή μέσω των
classes που εφαρμόζονται μέσα στο System.Reflection namespace.
Στο .ΝΕΤ, reflection σημαίνει έλεγχος του metadata για την ανάκτηση πληροφοριών για
ένα assembly, ένα module ή ένα type.
Το Visual Studio, π.χ., χρησιμοποιεί το reflection για την ανάκτηση Intellisense Data.
Assemblies, Modules και Types
Υπάρχουν τρία σχετικά namespaces:
System.Reflection.Assembly
System.Reflection.Module
System.Type
Το πρόγραμμα asminfo.cs που ακολουθεί, δείχνει πως το Reflection χρησιμοποιείται για
την ανάκτηση πληροφοριών για ένα αρχείο file.dll.
Παρατηρήστε τη χρήση των ακόλουθων τύπων:
• Assembly
• AssemblyName
• Version
• Module[ ]
• Type[ ]
• AssemblyName[ ]
asmInfo.cs
class MyApp {
static void Main (string[] args) {
if (args.Length == 0) {
Console.WriteLine ("Error: Missing file name");
return;
}
try {
Assembly a = Assembly.LoadFrom (args[0]);
AssemblyName an = a.GetName ();
byte[] bytes = an.GetPublicKeyToken ();
if (bytes == null)
Console.WriteLine ("Naming: Weak");
else
Console.WriteLine ("Naming: Strong");
Version ver = an.Version;
Console.WriteLine ("Version: {0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision);
Console.WriteLine ("nModules");
Module[] modules = a.GetModules ();
foreach (Module module in modules)
Console.WriteLine (" " + module.Name);
Console.WriteLine ("nExported Types");
Type[] types = a.GetExportedTypes ();
foreach (Type type in types)
Console.WriteLine (" " + type.Name);
Console.WriteLine ("nReferenced Assemblies");
AssemblyName[] names = a.GetReferencedAssemblies ();
foreach (AssemblyName name in names)
Console.WriteLine (" " + name.Name);
}
catch (Exception e) { Console.WriteLine (e.Message); }
}
}
Εφαρμοσμένα ως
collections
Χρήση pointers από C#
• Η C# μας επιτρέπει να γράψουμε "unsafe"
κώδικα.
• Ο Unsafe κώδικας δεν τρέχει κάτω από το
memory management του Common Language
Runtime (CLR).
• Οι Pointers είναι σαν τα references στη C#
(MyObject x = new MyObject()).
• Η κύρια διαφορά είναι ότι ο δείκτης μπορεί να
δείξει οπουδήποτε στη μνήμη
• Για να μεταγλωτιστεί unsafe κώδικας, πρέπει να
γίνει χρήση της επιλογής /unsafe στον compiler.
Παράδειγμα
unsafe
{
int* fib = stackalloc int[100];
int* p = fib;
*p++ = *p++ = 1;
for (int i = 2; i < 100; ++i, ++p)
*p = p[-1] + p[-2];
for (int i = 0; i < 10; ++i)
Console.WriteLine(fib[i]);
}
Attributes
Μπορούμε να φανταστούμε τις attributes ως τρόπους να “διακοσμήσουμε” ή να
καθορίσουμε λεπτομέρειες γύρω από μια δήλωση στον κώδικα μας. Για παράδειγμα, τα
access modifiers μιας class (public, protected, private) είναι attributes.
Οι attributes του SDK μπορούν να βρεθούν χρησιμοποιώντας το namespace
System.Reflection.{AssemblyConfigurationName, AssemblyCultureName, …}.
Η C# μας δίνει την δυνατότητα να ορίσουμε attributes στο επίπεδο του assembly, module,
class, struct, interface, enum, delegate, method, parameter, field, property (indexer, getter,
setter), event (field, property, add, remove).
Αυτό είναι δυνατόν γιατί υπάρχουν τρεις classes των attributes: AttributeUsage,
Conditional, and Obsolete.
Attributes, μέρος 2
Οι Attributes είναι δηλώσεις κώδικα που προστίθενται για να προσδιορίσουν ή να ανακτήσουν
πληροφορίες για metadata.
Αν χρησιμοποιηθούν έξυπνα, οι δηλώσεις attribute μπορούν να αποδειχτούν ένα εξαιρετικό
εργαλείο για τον ομαδικό προγραμματισμό και για τη διαχείριση των εκδόσεων (version
control).
Μια attribute εφαρμόζεται στο κομμάτι κώδικα που βρίσκεται αμέσως μετά από τη δήλωση
της:
using System.Diagnostics;
[Conditional ("DEBUG")]
public void DoStuff () { ... }
Αυτό καλείται «δώσιμο μιας attribute σε μια μέθοδο». Αν ο κώδικας γίνει compiled χωρίς ένα
“DEBUG” σύμβολο, ένα token τοποθετείται στο metadata για να υποδηλώσει ότι το DoStuff δε
θα κληθεί.
Αν κάποιος άλλος κώδικας καλέσει το DoStuff σε release mode, η κλήση θα αγνοηθεί. Το
DoStuff θα εκτελεστεί μόνο αν το module του γίνει compiled σε DEBUG mode.
Χρήση Attributes για Version Control
[AttributeUsage (AttributeTargets.All, AllowMultiple=true)]
class CodeRevisionAttribute : Attribute
{
public string Author; public string Date; public string Comment;
public CodeRevisionAttribute (string Author, string Date)
{
this.Author = Author; this.Date = Date;
}
}
Ο κώδικας μπορεί να χρησιμοποιηθεί ως εξής:
[CodeRevision ("billg", "07-19-2001")]
[CodeRevision ("steveb", "09-30-2001", Comment="Fixed Bill's bugs")]
struct Point
{
public int x; public int y; public int z;
}
Ο compiler προσθέτει
την Attribute
MemberInfo info = typeof (Point);
object[] attributes = info.GetCustomAttributes (false);
if (attributes.Length > 0) {
Console.WriteLine ("Code revisions for Point struct");
foreach (CodeRevisionAttribute attribute in attributes) {
Console.WriteLine ("nAuthor: {0}", attribute.Author);
Console.WriteLine ("Date: {0}", attribute.Date);
if (attribute.Comment != null)
Console.WriteLine ("Comment: {0}", attribute.Comment);
}
}
Code revisions for Point struct
Author: billg
Date: 07-19-2001
Author: steveb
Date: 09-30-2001
Comment: Fixed Bill's bugs
Χρήση Attributes για Version Control,
μέρος 2
Πληροφορίες από
τη Attribute
Το Dynamic Loading (δυναμική φόρτωση) αναφέρεται στη διαδικασία εισαγωγής modules
(τυπικά από .dll αρχεία) όταν χρειάζονται. Τα Plug-ins είναι ένα καλό παράδειγμα του
dynamic loading.
Το Dynamic Loading πραγματοποιείται χρησιμοποιώντας μια τεχνική που λέγεται “Late
Binding”, που ουσιαστικά γίνεται με την αναβολή της ανάθεσης των τύπων (type
assignment) ενός καινούργιου object μέχρι να χρειαστούν πληροφορίες για τους τύπους
(για να πάρουμε τα μέλη τους, το μέγεθος τους, κ.τ.λ.).
Το Reflection κάνει το Late Binding για το Dynamic Loading δυνατόν.
Late Binding
Threading
• Μπορούμε να χρησιμοποιήσουμε το namespace
System.Threading για τη δημιουργία
πολυνηματικών εφαρμογών
• Χρειάζεται ένας delegate ThreadStart ή
ParameterizedThreadStart (αν θέλουμε
παραμέτρους)
• Δημιουργία αντικειμένου Thread, με τον
αντίστοιχο delegate στον constructor
• Εκκίνηση του thread, με την
threadInstance.Start()
Παράδειγμαstatic void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(WriteToConsole);
Console.WriteLine("In parent thread, managed thread id = {0} and child thread id = {1}",
Thread.CurrentThread.ManagedThreadId, t.ManagedThreadId);
t.Start();
}
Console.ReadLine();
}
readonly static Random random = new Random(DateTime.Now.Millisecond);
static void WriteToConsole()
{
Thread.Sleep(random.Next(500,3000));
Console.WriteLine("In child thread, Time is {0} and ThreadID is
{1}",DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
}
Output
Task Parallel Library
Managed Extensibility Framework
Χρήσιμα Links
http://msdn.microsoft.com
http://www.studentguru.gr
http://www.dreamspark.com
http://www.studentguru.gr/b/dt008
http://www.imaginecup.com
Σας ευχαριστώ 
Console.WriteLine(new Func<string> (() => "Ερωτήσεις - Συζήτηση").Invoke());
//output: Ερωτήσεις - Συζήτηση
“True programming
languages use curly
brackets”
Anonymous, 2007

Εισαγωγή σε C# και .ΝΕΤ

  • 1.
    Εισαγωγή στο .ΝΕΤFramework και στη C# Δημήτρης – Ηλίας Γκανάτσιος Υπεύθυνος ακαδημαϊκών προγραμμάτων, Microsoft Hellas v-digkan@microsoft.com | twitter.com/dgkanatsios | facebook.com/dgkanatsios Version: 0.2.0.5, 11/3/2010
  • 2.
    Περιεχόμενα Τμήμα 1: Επισκόπησητου .NET Framework Τμήμα 2: C#, μέρος 1: Basic Language Constructs Types Statements Structures Classes Τμήμα 3: C#, μέρος 2 Delegates Events C# 3.0 και 4.0 Τμήμα 4: Base Class Library
  • 3.
    Τμήμα 1: Επισκόπησητου .NET Framework Τι είναι το .ΝΕΤ Common Language Runtime, Base Class Library Διαδικασία εκτέλεσης, Common Language Infrastructure
  • 4.
    Τι είναι το.ΝΕΤ Framework; Πλατφόρμα στην οποία μπορούμε να δημιουργήσουμε κάθε είδους εφαρμογές Περιλαμβάνει μηχανισμούς και βιβλιοθήκες: • Common language runtime (CLR) • Class libraries (BCL ή FCL) • Runtime Compiler (Jitter) • Virtual Execution System (VES)
  • 5.
  • 6.
    Εκδόσεις του .ΝΕΤ .NET1.0 .NET 1.1 .NET 2.0 3.0 3.5 .NET 4 2002 2003 20102005-08 CLR 1.0 CLR 1.1 CLR 2.0 CLR 4 SP1
  • 7.
    Το .NET Frameworkσε σχέση με το λειτουργικό
  • 8.
    Τεχνικές σχεδίασης του.ΝΕΤ • Διαλειτουργικότητα (Interoperability) • Common Language Runtime • Language Independence • Base Class Library • Simplified Deployment • Security • Portability
  • 9.
    Common Language Infrastructure –Το σύνολο της υποδομής του .ΝΕΤ Framework – Αποτελείται από • The Common Type System (CTS) Σύνολο τύπων και λειτουργιών που είναι κοινοί σε όλες τις CTS- συμβατές γλώσσες • Metadata Πληροφορίες για τους τύπους και τη δομή του εκτελέσιμου αρχείου ή της βιβλιοθήκης • Common Language Specification (CLS) Βασικοί κανόνες οι οποίοι θα πρέπει να τηρούνται από οποιαδήποτε γλώσσα κάνει target το CLI (ώστε να είναι .ΝΕΤ συμβατή) • Virtual Execution System (VES) Το VES φορτώνει και εκτελεί CLI-συμβατά προγράμματα και βιβλιοθήκες. – Είναι ανοικτό πρότυπο (ECMA-335 και ISO/IEC 23271) – Από Ιούλιο 2009: C# και CLI υπό Community Promise
  • 10.
    Common Type System •Στόχοι: – Να υπάρχει ένα framework που υποστηρίζει cross-language integration, type safety και εκτέλεση κώδικα με υψηλή απόδοση – Η παροχή ενός αντικειμενοστρεφούς μοντέλου, που υποστηρίζει την πλήρη υλοποίηση από διάφορες γλώσσες προγραμματισμού – Ο προσδιορισμός κανόνων που πρέπει να ακολουθούν οι γλώσσες προγραμματισμού, ώστε να είναι “interoperable”
  • 11.
    Common Language Specification •Οι CLS κανόνες προσδιορίζουν ένα υποσύνολο του CTS • Όλοι οι κανόνες του CTS εφαρμόζονται και στο CLS, εκτός αν υπάρχει κάποιος «αυστηρότερος» στο CLS • Το CLS βοηθάει στο “language interoperability” με το να προσδιορίζει χαρακτηριστικά που είναι κοινά σε κάθε γλώσσα που κάνει target το CLR • Example: – UInt32 δεν είναι CLSCompliant – C# case sensitive, Visual Basic όχι
  • 12.
  • 13.
    Common Language Runtime •Just-in-time Compilation • Memory management • Garbage collection • Thread management • Exception handling • Security • Type safety
  • 14.
  • 15.
    Application Domain • Έναapplication domain για το CLR είναι κάτι παρεμφερές με το ό,τι είναι μία διεργασία (process) για το λειτουργικό σύστημα • Χρησιμοποιείται για να απομονώσει τις εφαρμογές που εκτελούνται – Ώστε η μία να μην επηρεάζει και να εκτελείται ανεξάρτητα από την άλλη
  • 16.
    Συλλογή απορριμμάτων 1/2 •Ο προγραμματιστής δημιουργεί νέα αντικείμενα και πίνακες – Τα πάντα δημιουργούνται και η μνήμη δεσμεύεται με ένα ειδικό keyword. • Το περιβάλλον εκτέλεσης του .NET παρακολουθεί αυτόματα τη χρήση μνήμης • Ο Garbage Collector αφαιρεί αυτόματα τα αχρησιμοποίητα αντικείμενα • Πιο αποτελεσματική διαχείριση μνήμης • Ευκολία στη χρήση και “μηδενικές διαρροές”
  • 17.
    Συλλογή απορριμάτων 2/2 AB C D E F A C E Τα B,D βγαίνουνε out of scope, με το F να «κρέμεται» από το B Κλήση της GC.Collect() NextObjectPointer … … NextObjectPointer
  • 18.
    Τι μπορούμε ναπρογραμματίσουμε; • Εφαρμογές κονσόλας • Εφαρμογές για Windows (διεπαφή χρήστη σε Windows Forms) • Εφαρμογές για Windows με το Windows Presentation Foundation (WPF) • ASP.NET εφαρμογές που εκτελούνται σε Web Servers • Web services • Windows services • Service-oriented applications using Windows Communication Foundation (WCF) • Workflow-enabled applications using Windows Workflow Foundation (WF) • Silverlight Applications • Mobile Applications (Compact Framework) • Embedded Applications (Micro Framework) • Office Applications (VSTO) • SharePoint Applications • XBOX 360 Games, PC Games, Zune Games (XNA) • Windows 7 (με το Windows 7 API Code Pack) – συμπεριλαμβάνεται Sensor και Location Platform • Visual Studio Tools for Office • Microsoft Dynamics CRM • Οτιδήποτε έχει API σε .ΝΕΤ!
  • 19.
    Τι βιβλιοθήκες μπορούμενα χρησιμοποιήσουμε; • Base Class Library (BCL) – Χιλιάδες έτοιμες κλάσεις για το προγράμματά μας – Προσβάσιμες σε κάθε σύστημα που έχει εγκατεστημένο το .NET Framework – Διαθέσιμες από εύκολα αναγνωρίσιμους χώρους ονομάτων, π.χ. System.Data.SqlClient.SqlConnection System.Windows.Forms.Form System.Net.Sockets.TcpClient System.Xml.XmlReader • Χιλιάδες code samples και open source projects που παρέχονται δωρεάν στο διαδίκτυο • www.codeplex.com • code.msdn.microsoft.com • blogs.msdn.com • weblogs.asp.net
  • 21.
    Ωφέλη του .NETFramework • Many languages, One Intermediate Language, Many platforms • Αποχαιρετήστε τα memory leaks (Garbage Collector) • Optimization per CPU / platform • Ένα περιβάλλον προγραμματισμού για πολλών ειδών εφαρμογές • Ιδανικό μοντέλο ασφάλειας • Deployment
  • 22.
    Γιατί C# ? Μιαcomponent-oriented γλώσσα Επαναχρησιμοποιήσιμες βιβλιοθήκες Εγγενής υποστήριξη για Namespaces Versioning Attribute-driven ανάπτυξη Η δύναμη της C/C++ με την ευκολία της Visual Basic Ελάχιστη καμπύλη εκμάθησης για όλους Πιο σαφής από την C++ Πιο δομημένη από τη Visual Basic Περισσότερες δυνατότητες από τη Java Δυνατότητες functional programming (όπως η Haskell, η Scheme κ.λ.π.) Δυνατότητες dynamic programming (έκδοση 4)
  • 23.
    Τμήμα 2: C#- The Language
  • 24.
    Μορφή και Δομή Δενυπάρχουν header files Μεταγλώττιση υπό συνθήκη – αλλά όχι macros Μεταγλώττιση σε .NET assembly (είτε .exe είτε .dll) Μόνο object oriented κώδικα Main() entry point του προγράμματος (μόνο για εκτελέσιμα αρχεία)
  • 25.
    Hello World public classHelloWorld { public static void Main() { System.Console.WriteLine("Hello World!"); } }
  • 26.
    Visual Studio • IDE(Integrated Development Environment) • Γλώσσες: C++, C#, F#, Visual Basic κ.α. • Δωρεάν πρόσβαση – Για φοιτητές: MSDNAA – www.dreamspark.com – Για startups: www.bizspark.com – Για web agencies: www.websitespark.com • Express editions: www.microsoft.com/express • Web Platform Installer: www.microsoft.com/web
  • 27.
    Σύστημα τύπων • Εγγενήςπρόσβασή στο σύστημα τύπων του .NET • Βασικές έννοιες: –Τα πάντα είναι objects • Τα πάντα κληρονομούν το System.Object –Ξεκάθαρη διάκριση ανάμεσα στους τύπους τιμής και αναφοράς • Με τιμή: απλοί τύποι, enums, structs • Με αναφορά: Interfaces, Κλάσεις, Πίνακες
  • 28.
    Απλοί Τύποι • ΤύποιΑκεραίων – byte, sbyte (8bit), short, ushort (16bit) – int, uint (32bit), long, ulong (64bit) • Τύποι κινητής υποδιαστολής (IEEE) – float (ακρίβεια 7 ψηφίων) – double (ακρίβεια 15–16 ψηφίων) • Exact Numeric Type – decimal (28 σημαντικά ψηφία) • Τύποι Χαρακτήρων – char (ένας χαρακτήρας) – string (πλούσια λειτουργικότητα, τύπος αναφοράς) • Τύποι Boolean bool (ξεχωριστός τύπος, διαφορετικός από τον int)
  • 29.
    Value Types καιReference Types • Κατά κανόνα, τα value types είναι οι απλοί τύποι (int, double, byte κ.λ.π.) και οι δομές (struct) – Το System.String ενώ είναι reference type, το χρησιμοποιούμε σαν value type • Reference types είναι οι υπόλοιποι τύποι (όλες οι κλάσεις, events, delegates κ.λ.π.) • Αποθήκευση στη μνήμη του προγράμματος – τα value types (όταν δηλώνονται μέσα σε μια μέθοδο) αποθηκεύονται στη στοίβα (stack) – τα reference types (μαζί με τα value types τα οποία μπορεί να περιέχουν) αποθηκεύονται στο σωρό (heap)
  • 30.
    ‘Πέρασμα’ μεταβλητών σεμεθόδους • Πέρασμα τιμών χωρίς keyword (κατ’αξία) μη διατηρήσιμη αλλαγή τιμής • Πέρασμα τιμών με το ref keyword (κατ’αναφορά) επιτρέπεται αλλαγή τιμής • Πέρασμα τιμών με το out keyword (output) επιβάλλεται ανάθεση τιμής
  • 31.
    Δηλώσεις (Statements) Έλεγχος ροήςκαι επαναλήψεις if (<bool expr>) { ... } else { ... }; switch(<var>) { case <const>: ...; }; while (<bool expr>) { ... }; for (<init>;<bool test>;<modify>) { ... }; do { ... } while (<bool expr>);
  • 32.
    Απαριθμητοί Τύποι (Enums) Χρησιμοποιούνταιστοιχεία με όνομα αντί για αριθμητικές επιλογές Ισχυρός τύπος, όχι αυτόματη μετατροπή σε int Καλύτερο το "Color.Blue" από μια αριθμητική έκφραση Πιο κατανοητό, ευκολότερη συντήρηση Εξίσου ελαφρύ με το απλό int (αν δεν δηλωθεί άλλος τύπος στο enum) Παράδειγμα: enum Color { Red, Green, Blue, Yellow };
  • 33.
    Πίνακες (Arrays) Zero based,type bound Βασίζονται στην .NET κλαση System.Array Δηλώνονται με τύπο και μορφή, αλλά χωρίς όρια int[] SingleDim; int[,] TwoDim; int [][] Jagged; Δημιουργούνται με χρήση του new με όρια ή initializers SingleDim = new int[20]; TwoDim = new int[,]{{1,2,3},{4,5,6}}; Jagged = new int[1][]; Jagged[0] = new int[]{1,2,3};
  • 34.
    Τελεστές (Operators) Σαν τηC: Λογικοί/Συνθήκης: && || ^ Αριθμητικοί: * / + - % << >> Σχεσιακοί: == != < > >= <= Όχι ακριβώς σαν τη C: Για bool: & και | είναι λογικοί με πλήρη απαρίθμηση Για ακεραίους: & και | υλοποιούν δυαδικό AND/OR Καθόλου σαν τη C: is Ελέγχει τον run-time τύπο as Μετατρέπει μια τιμή σε άλλο τύπο typeof Ανακτά τον run-time τύπο
  • 35.
    Structures • Είναι valueTypes • Ιδανικά για μικρούς τύπους δεδομένων • Μπορούν να περιέχουν μεθόδους • Τα fields μπορεί να είναι public, private ή internal • Δεν μπορούν να κάνουν inherit κλάση • Μπορούν να κάνουν implement interface struct MyStruct { public int i; private string s; public void WriteToConsole() { Console.WriteLine("I am a struct"); } }
  • 36.
    Κλάσεις Υλοποίηση κώδικα καιδεδομένων Αναπαριστά μια σημασιολογική ενότητα Μπορεί να υλοποιεί interfaces Μπορεί να κληρονομεί από μία βασική κλάση (base class) Οι κλάσεις περιέχουν: Πεδία (Fields): μεταβλητές μελών Ιδιότητες (Properties): τιμές στις οποίες γίνεται πρόσβαση με ζευγάρια μεθόδων get/set Μέθοδοι (Methods): λειτουργικότητα για το αντικείμενο ή την κλάση Άλλα: events, indexers, delegates public class Person : IPersonAge { private int YOB; public Person() { } public int YearOfBirth { get { return YOB; } set { YOB = value; } } public int GetAgeToday() { return Today()- YearOfBirth ; } }
  • 37.
    Ιδιότητες (Properties) Ευκολία υλοποίησηςμεθόδων Χρησιμοποιούμε properties για: Υλοποίηση read-only μελών (παραλείποντας το set) Επικύρωση κατά την ανάθεση Παράγωγες ή σύνθετες τιμές Έκθεση τιμών στα interfaces Παράδειγμα: string Name { get { return name; } set { name = value; } }
  • 38.
    Χώροι Ονομάτων (Namespaces) •Κάθε ορισμός πρέπει να περιέχεται σε ένα namespace – Αποφεύγεται η σύγκρουση ονομάτων – Καλύτερη οργάνωση – Οι βιβλιοθήκες γίνονται ευκολότερες στην κατανόηση • Μπορούν να εμφωλιάζονται • Ομάδες κλάσεων και τύπων κατά χρησιμότητα • Δηλώνονται με τη λέξη-κλειδί namespace • Συντόμευση για χρήση σε κώδικα, με using
  • 39.
    Iteration με χρήσητης foreach List<string> stringList = new List<string>(); stringList.Add("one"); stringList.Add("two"); stringList.Add("three"); stringList.Add("four"); //stringList.Add(5); won’t compile, as 5 is not a string foreach(string s in stringList) if(s.Contains("e")) Console.WriteLine(s); Χρησιμοποιείται σε arrays και collections. Προσοχή: Μέσα από την foreach, ΔΕΝ πειράζουμε την collection (π.χ. Δεν κάνουμε κάποιο add ή remove, καθώς έτσι «σπάει» ο Enumerator)
  • 40.
    Κληρονομικότητα – Πολυμορφισμός1 • Η C# υποστηρίζει κληρονομικότητα • Κάθε κλάση μπορεί να κληρονομήσει χαρακτηριστικά μόνο μίας κλάσης • Πολλαπλή κληρονομικότητα δεν υποστηρίζεται (παρά μόνο (κάπως) με τα Interfaces) • Χρήση των λέξεων abstract, sealed, virtual, new
  • 41.
    Κληρονομικότητα – Πολυμορφισμός2 class Parent { public void A(){...}; public virtual void B(){...}; } class Child : Parent { public new void A(){...}; //A() not declared as virtual on Parent public override void B(){...}; //B() declared as virtual on Parent } public static void Main() { Child c = new Child(); c.A(); // Child::A() c.B(); // Child::B() Parent p = c as Parent; p.A(); // Parent::A() p.B(); // Child::B() }
  • 42.
    Προστασία Πρόσβασης Υιοθετεί τομοντέλο της C++ public  Όλοι μπορούν να καλέσουν ή να έχουν πρόσβαση protected  Μόνο τα μέλη έχουν πρόσβαση private  Μόνο τα μέλη και μόνο αυτής της κλάσης Αλλά και το επεκτείνει Modifiers για κλάσεις sealed  Δεν μπορεί να χρησιμοποιηθεί σαν βασική κλάση internal  Public πρόσβαση μόνο μέσα στην assembly protected internal  Protected στην assembly (σημαίνει protected OR internal) abstract  δεν μπορεί να γίνει instantiate, αλλά μπορεί μόνο να κληρονομηθεί
  • 43.
    Abstract classes -Interfaces • Abstract classes : υποχρεωτικά κληρονομούνται – Μπορούν να έχουν υλοποιήσεις μεθόδων, ή σκέτες δηλώσεις – Μπορούν να έχουν fields – Αν θέλουμε μια κλάση να *μην* μπορεί να κληρονομηθεί, τότε τη χαρακτηρίζουμε ως sealed • Interfaces: Συμβόλαια δήλωσης σημασιολογίας μεταξύ δύο μερών – Μπορούν να γίνουν implement από structures ή classes – Δεν έχουν υλοποιήσεις μεθόδων, αλλά μόνο δηλώσεις – Μπορούν να έχουν δηλώσεις από properties • Παράδειγμα: interface IPersonAge { int YearOfBirth {get; set;} int GetAgeToday(); }
  • 44.
    Οι λέξεις isκαι as • is: έλεγχος για τον τύπο ενός αντικειμένου if(objectInstance is MyClass) • as: αποτρέπει InvalidCastException από μη επιτρεπτό cast αντί π.χ. για (MyClass)objectInstance το οποίο μπορεί να επιφέρει Exception, χρησιμοποιούμε το objectInstance2 = objectInstance as MyClass – Αν το cast είναι επιτρεπτό, επιστρέφει objectInstance – Ειδάλλως, επιστρέφει null
  • 45.
    Η λέξη static •Όταν χαρακτηρίσουμε ένα property ή μεταβλητή μιας κλάσης με τη λέξη static, τότε η τιμή της είναι η ίδια για κάθε instance της κλάσης • Όταν χαρακτηρίσουμε μια κλάση με τη λέξη static, τότε δεν μπορούμε να δημιουργήσουμε instance αυτής της κλάσης – Χρήσιμο για καταστάσεις που χρειαζόμαστε ένα και μόνο instance μιας κλάσης – Οι static κλάσεις έχουνε αποκλειστικά static μέλη
  • 46.
    Generics • Παρόμοια μετα templates της C++ • Επιτρέπουν type safety • Εύκολος τρόπος για πιο «γενικά» αντικείμενα • Π.χ. εκτύπωση των αντικειμένων ενός πίνακα void Print<T>(T[] myArray) { foreach(T myObject in myArray) Console.WriteLine(myObject.ToString()); } Περισσότερα για generics: http://msdn2.microsoft.com/en-us/library/ms379564(VS.80).aspx
  • 47.
    Iterators • Εισήχθησαν στηνC# 2.0 • Είναι μία μέθοδος, get accessor που επιτρέπει την χρήση επανάληψης (for, foreach, while, do while) στην κλάση ή το struct χωρίς να χρειάζεται να υλοποιηθεί το interface IEnumerable • Αποτελείται από ένα κομμάτι κώδικα που «επιστρέφει» ταξινομημένη σειρά τιμών ίδιου τύπου • Χρησιμοποιεί το yield return
  • 48.
    Παράδειγμα public class SampleCollection { publicint[] items = new int[5] { 5, 4, 7, 9, 3 }; } public IEnumerable><int> BuildCollection() { for (int i = 0; i < items.Length; i++) //το πρόγραμμα θα γυρίσει εδώ μετά την { //εκτέλεση της yield yield return items[i]; } } } class MainClass { static void Main() { SampleCollection col = new SampleCollection(); foreach (int i in col.BuildCollection()) { Console.WriteLine(i); } } }
  • 49.
    Nullable Types • Μετην χρήση των nullable types, μπορούμε να καταχωρήσουμε την τιμή null σε κάποιον value type – Π.χ. int? x; //ίδιο με το Nullable<int> x; x = null; – Μπορούμε να ελέγξουμε για ύπαρξη τιμής με το if(x.HasValue) – Μπορούμε να πάρουμε την τιμή (αφού ελέγξουμε για HasValue) με int y = x.Value; • Χρήσιμα όταν περιμένουμε είτε «κανονική», είτε null τιμή από κάπου (π.χ. βάση δεδομένων με nullable πεδίο)
  • 50.
    Αντιπρόσωποι (Delegates) • Κάτισαν τους δείκτες σε συναρτήσεις (C/C++) • Ισχυροί τύποι, όχι σύγχυση στο type-casting ή σφάλματα. • Η δήλωση δημιουργεί μια typed method signature: – delegate void Clicked(Element e, Point p); • Ο πραγματικός αντιπρόσωπος είναι ένα στιγμιότυπο αυτού του τύπου – Clicked MyClickHandler = new Clicked(obj.OnButtonClick); • Το όρισμα περνιέται στον constructor του αντιπροσώπου: – Αναφορά στο στιγμιότυπο του αντικειμένου και στη μέθοδο. – Η μέθοδος πρέπει να έχει την ίδια ακριβώς υπογραφή • void OnButtonClick(Element e, Point p) { ... };
  • 51.
    Συμβάντα (Events) • Μοντέλοσυμβάντων ενσωματωμένο στη γλώσσα • Όλη η διαχείριση γίνεται από τη C# • Τα events δηλώνονται με έναν τύπο delegate • Η δήλωση δημιουργεί μια πηγή συμβάντος για να γίνει bind – event Clicked OnClicked; – Τα event sinks γίνονται bind στην πηγή του συμβάντος με delegates Clicked MyClickHandler = new Clicked(obj.OnButtonClick); – Προσθήκη handler: • btnAction.OnClicked += MyClickHandler; – Απαλοιφή handler: • btnAction.OnClicked -= MyClickHandler; • Η πηγή του συμβάντος “πυροδοτεί” events με μια απλή κλήση – if(OnClicked != null) OnClicked(this,PointerLocation);
  • 52.
    Χειρισμός Εξαιρέσεων • Παρόμοιοςμε τη C++ • Μοντέλο SEH (Structured Exception Handling) • Διαβάζεται ως εξής: – try να τρέξεις αυτό τον κώδικα... – ... αν προκύψει σφάλμα, catch ό,τι μπορείς να χειριστείς... – ...finally άφησε με να τελειώσω το cleanup με το χέρι • Παράδειγμα: try { //... run code } catch(SomeException e) { //... handle } finally { //...end gracefully }
  • 53.
    Partial Classes Partial classes:Η υλοποίηση μιας κλάσης μπορεί να ‘σπάσει’ σε πολλά αρχεία – Βοηθάει στην ανάπτυξη λογισμικού από ομάδες προγραμματιστών – Χρησιμοποιούμε τη λέξη partial στον ορισμό της κλάσης – Βοηθάει στο διαχωρισμό κώδικα διαφορετικής χρηστικότητας • Παράδειγμα: Σε μια Windows Forms εφαρμογή, έστω ότι δημιουργούμε μια καινούρια Form, ονόματι MyForm. Τότε: – Ο κώδικας που δημιουργείται από τον Visual Studio designer της φόρμας (με drag-drop κ.λ.π.) τοποθετείται στο αρχείο MyForm.Designer.cs – Ο κώδικας που γράφουμε εμείς τοποθετείται στο MyForm.cs
  • 54.
    Anonymous methods • Anonymousmethods : in-line κατασκευή μιας συνάρτησης η οποία προορίζεται για χρήση μέσω delegate – Ελάττωση του απαιτούμενου κώδικα για «μικρές» συναρτήσεις
  • 55.
  • 56.
    Η μεγαλύτερη καινοτομίατης C# 3.0 Μεγαλύτερη καινοτομία: επερωτήσεις στα δεδομένα, οτιδήποτε είδους var query = from p in employees where p.Salary > 33000m orderby p.Name, p.StartDate descending select p.Name;
  • 57.
    Anonymous types Σαν έναςκανονικός τύπος που ζει στο CLR var v = new { Amount = 108, Message = "Hello" };
  • 58.
    Extension methods • Επιτρέπεταινα προστεθούν μέθοδοι σε υπάρχοντες τύπους χωρίς να δημιουργούμε έναν νέο derived τύπο • Καλούνται πολύ εύκολα (just static methods underneath) • Method chaining
  • 59.
    Παράδειγμα • string x= "some string value"; string y = Utility.Reverse(x); • string x = "some string value"; string y = x.Reverse(); public static class Utility { public static string Reverse(this string input) { char[] chars = input.ToCharArray(); Array.Reverse(chars); return new String(chars); } }
  • 60.
    Lambda expressions • Σανanonymous method αλλά μικρότερο • Χρησιμοποιεί τον lambda operator => που διαβάζεται goes to δηλαδή «συνεπάγεται» • Αριστερά έχουμε παραμέτρους εισόδου και δεξιά την έκφραση ή το κομμάτι κώδικα. • Shorthands – Parameter type inference – Brace removal (single expression/statement) – Bracket removal (single parameter) • Expression Trees
  • 61.
    Παράδειγμα int[] source =new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 }; foreach (int i in source.Where(x => x > 5)) Console.WriteLine(i);
  • 62.
    Παράδειγμα (C# 1.0) //Δήλωση delegate public delegate int ChangeInt(int x); // Μία μέθοδος στην οποία μπορεί να δείξει η από πάνω μεταβλητή static public int DoubleIt(int x) { return x * 2; } // Δημιουργία στιγμιοτύπου ChangeInt myDelegate = new ChangeInt(DelegateSample.DoubleIt); Console.WriteLine("{0}", myDelegate(5));
  • 63.
    Παράδειγμα (C# 2.0) ChangeIntmyDelegate = new ChangeInt( delegate(int x) { return x * 2; } ); Console.WriteLine("{0}", myDelegate(5));
  • 64.
    Παράδειγμα (C# 3.0) ChangeIntmyDelegate = x => x * 2; Console.WriteLine("{0}", myDelegate(5));
  • 65.
    LINQ Χαρακτηριστικά • Δυνατότητα επερωτήσεων μέσαστη γλώσσα • Περιέχει Standard Query Operations – Select – Where – Join – Take/Skip – Group By • Providers
  • 66.
  • 67.
    Τμήμα 4: BaseClass Libraries
  • 68.
    Dictionaries Τα Dictionaries είναιδομές δεδομένων που αποθηκεύουν ζευγάρια key/values σε θέσεις που λέγονται KeyValuePair. Το κυριότερο πλεονέκτημα των Dictionaries είναι ότι η αναζήτηση είναι πολύ γρήγορη γιατί η «σκληρή» δουλειά γίνεται κατά τη φάση της αποθήκευσης. Στην ουσία, ένα μοναδικό κλειδί αποκτάται για την αποθήκευση των τιμών στα KeyValuePair. Ένας συνηθισμένος κώδικας που χρησιμοποιεί Dictionaries περιλαμβάνει: Dictionary<string, string> aDict = new Dictionary<string, string>(); aDict.Add("Sunday", "Dimitris"); // (key,value) pair aDict["Monday"] = "Gkanatsios"; // aDict ]=value; foreach (KeyValuePair<string, string> entry in aDict) Console.Write("Key={0}, Value={1}n", entry.Key, entry.Value);
  • 69.
    Arrays Υπάρχουν δύο τύποιarrays στο .NET: Array είναι μια class που προέρχεται κατεθευθείαν από το System.Object. Αυτή η class μπορεί να χρησιμοποιηθεί για να υλοποιήσετε στατικές (συγκεκριμένου μεγέθους) arrays για την αποθήκευση πρωτόγονων τύπων. Ένα element (στοιχείο) είναι μια τιμή μέσα στην Array. Το length είναι ο συνολικός αριθμός των elements μέσα στο array. Το rank του Array είναι ο αριθμός των διαστάσεων του. Το κάτω όριο μιας διάστασης ενός Array είναι ο πρώτος αριθμοδείκτης εκείνης της διάστασης του Array. Μια πολυδιάστατη Array μπορεί να έχει διαφορετικά όρια για κάθε διάσταση. Τα Type objects παρέχουν πληροφορίες για την δήλωση των array type. Τα Array objects με τον ίδιο Array type μοιράζονται το ίδιο Type object. Το Array έχει 6 ιδιότητες (IsFixedSize, IsReadOnly, IsSynchronized, Length, Rank, SyncRoot), 22 μεθόδους ( BinarySearch, Clear, Copy, Equals, GetValue, GetLength, IndexOf, Initialize, Reverse, SetValue, Sort, ToString, Finalize κ.α.). Η class επίσης εφαρμόζει διάφορες μεθόδους της IList, που περιλαμβάνουν τα ( Add, Clear, Contains, IndexOf, Insert, Remove, RemoveAt ).
  • 70.
    ArrayList H ArrayList είναιμια class που προέρχεται από το System.Collections. Αυτή η class δεν έχει καμία σχέση με τη class System.Object.Array. Η δήλωση της class είναι: public class ArrayList : IList, ICollection, IEnumerable, ICloneable Το κείμενο δείχνει τις εξής ιδιότητες της class: ArrayList aList = new ArrayList (); aList.Add ("John"); aList.Add ("Paul"); aList.Add ("George"); Για την ανάκτηση ενός αντικειμένου από την ArrayList, χρησιμοποιήστε μια αριθμοδότηση βασισμένη στο 0: int i = (int) list[0]; Για την ανάθεση ενός αντικειμένου στην ArrayList, κάνουμε το εξής: list[0] = 999; Η ιδιότητα Count αποκαλύπτει πόσα αντικείμενα περιέχει μια ArrayList. for (int i=0; i<list.Count; i++) Console.WriteLine ( list[i] ); Μπορείτε να ανατρέξετε την ArrayList με το foreach: foreach (int i in list) Console.WriteLine (i);
  • 71.
    List<T> • Generic μορφήτου ArrayList List<int> list = new List<int>(); for (int i = 0; i < 100; i++) list.Add(i * 2); list.Add("string"); //compilation error
  • 72.
    Regular Expressions Το RegExείναι μια class προερχόμενη από το name space System.Text.RegularExpressions. Τα RegEx αντικείμενα μπορούν να χρησιμοποιηθούν για: • Να χωριστούν strings σε substrings, χρησιμοποιώντας τα RegExps για να αναγνωριστούν τα διαχωριστικά. • Να ψάξετε για substrings μέσα στα strings, χρησιμοποιώντας τις RegEx εκφράσεις για να αναζητήσετε σχέδια (patterns). • Να κάνετε λειτουργίες Αναζήτησης-Αντικατάστασης χρησιμοποιώντας το RegEx για να αναγνωρίσετε αυτά που πρέπει να αντικατασταθούν στο κείμενο. • Ανάλυση αρχείων HTML. Όταν δημιουργούνται RegEx objects, η έκφραση που περιγράφει το pattern χρησιμοποιείται ως ένα όρισμα στο constructor: using System.Text.RegularExpressions; Regex regex = new Regex ("[a-z]"); Regex regex = new Regex ("[a-z]", RegexOptions.IgnoreCase); Regex regex = new Regex (@""); string[] parts = regex.Split (@"c:inetpubwwwrootwintellect"); foreach (string part in parts) Console.WriteLine (part); c: inetpub wwwroot wintellect Οποιοδήποτε μικρό γράμμα της αλφαβήτας Επιστρέφει τα substrings μέσα στο string διαχωρισμένα από το όρισμα μέσα στο RegExp
  • 73.
    Χρήση του RegEx,μέρος 2 Για την ανάλυση ενός αρχείου html, με, π.χ., <b>Every</b>good<h3>boy</h3>does<b>fine</b> Regex regex = new Regex ("<[^>]*>"); string[] parts = regex.Split ("<b>Every</b>good<h3>boy</h3>does<b>fine</b>"); foreach (string part in parts) Console.WriteLine (part); Αυτός ο κώδικας παράγει: “Every good boy does fine” (μια λέξη ανά γραμμή). Παρατηρήστε ότι “<[^>]*>” σημαίνει: οτιδήποτε ξεκινά με “<” ακολουθόμενο από οποιουσδήποτε χαρακτήρες εκτός από το “>”, ακολουθόμενο από το “>”. To Regex περιλαμβάνει 3 μεθόδους για αναζήτηση substrings μέσα σε strings: Match, Matches, και IsMatch. Με αυτά, είναι αρκετά εύκολο να γράψει κανείς grep-like. Το πρόγραμμα μπορεί να χρησιμοποιηθεί για να κάνει οποιαδήποτε greps, όπως π.χ. NetGrep index.html “<a[^>]*>” Η παραπάνω εντολή θα εμφάνιζε τις γραμμές μέσα στις οποίες εμφανίζεται το <a> στο αρχείο index.html. Παρόμοια, η εντολή NetGrep file1.txt “d{2,}” Θα εμφάνιζε τις γραμμές που περιλαμβάνουν ακέραιους αριθμούς με δύο ή περισσότερα ψηφία μέσα στο file1.txt, κ.τ.λ.
  • 74.
    Χρήση του RegEx,μέρος 3 using System; using System.IO; using System.Text.RegularExpressions; class MyApp { static void Main (string[] args) { if (args.Length < 2) { Console.WriteLine ("Syntax: NETGREP filename expression"); return; } StreamReader reader = null; int linenum = 1; try { // Initialize a Regex object with the regular expression // entered on the command line Regex regex = Regex (args[1], RegexOptions.IgnoreCase); // Iterate through the file a line at a time and display all lines that contain a pattern matching the regular expression reader = new StreamReader (args[0]); for (string line = reader.ReadLine (); line != null; line = reader.ReadLine (), linenum++) { if (regex.IsMatch (line)) Console.WriteLine ("{0:D5}: {1}", linenum, line); } } catch (Exception e) { Console.WriteLine (e.Message); } finally { if (reader != null) reader.Close (); } } }
  • 75.
    Internet Classes Αυτές οιclasses υπάρχουν στο name space System.Net. Υπάρχουν 36 classes, 5 interfaces, ένα delegate, και 4 enumerations. Οι πιο σημαντικές classes είναι: Cookie, CookieCollection, Dns, HttpWebRequest, HttpWebResponse, HttpVersion, HttpWebRequest, HttpWebResponse, IPAddress, IPEndPoint, IPHostEntry, NetworkCredential, ProtocolViolationException, SocketAddress, WebClient, WebException, WebPermission, WebProxy, WebRequest, WebResponse και άλλα. Ο επόμενος κώδικας δείχνει μόνο πως να χρησιμοποιήσετε το WebRequest και WebResponse στο LinkList.cs, που παίρνει ένα URL ως όρισμα. Η εφαρμογή πάει στο URL και εμφανίζει τις γραμμές που περιλαμβάνουν αναφορές σε άλλα websites, π.χ. Υπερσυνδέσμους. Ο κώδικας είναι αρκετά απλός.
  • 76.
    System.Net.Mail Είναι αρκετά εύκολονα στείλετε e-mail από ένα .NET Framework πρόγραμμα (αρκεί να έχετε τις σωστές άδειες). Το System.Net.Mail παρέχει ένα managed interface για το SMTP. Οι κυριότερες classes είναι: 1. MailMessage, που αναπαριστά τα μηνύματα emails; 2. MailAttachment, που αναπαριστά τα συννημένα αρχεία; 3. SmtpClient, που χειρίζεται την υπηρεσία μηνυμάτων SMTP του συστήματος. Αυτά είναι τα βήματα για να σταλθούν emails με το System.Web.Mail: MailMessage message = new MailMessage(); message.From = new MailAddress("v-digkan@microsoft.com"); message.To.Add(new MailAddress("dt008@hotmail.com")); message.Subject = "test subject"; message.Body = "test body..."; SmtpClient cl = new SmtpClient(); cl.Host = "mail.gkanatsios.com"; cl.Send(message);
  • 77.
    Data Access • Πληθώρααπό τεχνολογίες Βάσεων Δεδομένων (ODBC, DAO, RDO, ADO, και OLEDB). • Συνέπραξαν στην πορεία προς το ADO.NET, το οποίο εφαρμόζεται στο System.Data namespace. • Το ADO.NET έχει δύο βασικούς τύπους classes, αυτούς που είναι βελτιστοποιημένοι για τον Microsoft SQL Server και όλους τους άλλους που περιλαμβάνονται στο OleDB, το οποίο δεν είναι γρήγορο αλλά είναι πιο γενικό. Οι base classes είναι: • Connection (OleDbConnection, SqlConnection) • Command (SqlCommand and OleDbCommand) • DataReader (OleDbDataReader, SqlDataReader) • DataSet • DataAdapter (SqlDataAdapter, OleDbDataAdapter) • Exception (SqlException, OleDbException
  • 78.
    Data Readers, παράδειγμα SqlConnectionconnection = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs"); connection.Open(); SqlCommand command = new SqlCommand("select * from titles", connection); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) Console.WriteLine(reader.GetString(1)); connection.Close(); Για απλότητα, ο παραπάνω κώδικας δε διαχειρίζεται τυχόν σφάλματα.
  • 79.
    Data Readers, μέρος2 SqlConnection connection = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs"); try { connection.Open(); SqlCommand command = new SqlCommand("select * from titles", connection); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) Console.WriteLine(reader.GetString(1)); } catch (SqlException e) { Console.WriteLine(e.Message); } finally { connection.Close(); } Παρόμοιος κώδικας μπορεί να χρησιμοποιηθεί για οποιοδήποτε άλλον OleDb data provider, απλά αντικαθιστώντας τους SQL types με τους αντίστοιχους OleDB types.
  • 80.
    Updating Data Όπως τοόνομα υπονοεί, οι Data Readers μπορούν μόνο να πάρουν δεδομένα από μια πηγή δεδομένων. Αν χρειάζονται λειτουργίες εγγραφής, τότε χρειάζεται ένα command object. SqlConnection connection = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs"); try { connection.Open(); string sqlcmd = "insert into titles (title_id, title, type, pub_id, price, advance, royalty, ytd_sales, notes, pubdate) values ('BU1001', 'Programming Microsoft.NET', 'Business', '1389', NULL, NULL, NULL, NULL, 'Learn to program Microsoft.NET', 'Jan 01 2002')"; SqlCommand command = new SqlCommand(sqlcmd, connection); command.ExecuteNonQuery(); } catch (SqlException e) { Console.WriteLine(e.Message); } finally { connection.Close(); }
  • 81.
    DataSets και DataAdapters ΤοDataSet είναι η αναπαράσταση μιας βάσης δεδομένων αποθηκευμένη στη μνήμη και μπορεί να περιέχει πολλαπλούς πίνακες δεδομένων με constraints και relationships. Τα DataSets χρησιμοποιούνται μαζί με τους DataAdapters για τη διευκόλυνση της πρόσβασης ανάγνωσης/γραφής στις βάσεις δεδομένων. SqlDataAdapter adapter = new SqlDataAdapter("select * from titles","server=localhost;uid=sa;pwd=;database=pubs"); DataSet ds = new DataSet(); adapter.Fill(ds); foreach (DataRow row in ds.Tables[0].Rows) Console.WriteLine(row[1]); Παρατηρήστε τη χρήση του foreach, η οποία σημαίνει ότι το DataSet έχει collections από στήλες και γραμμές.
  • 82.
    LINQ To SQL •Το Linq To SQL είναι ένας εξελιγμένος O/R Mapper που μας επιτρέπει εύκολη πρόσβαση σε δεδομένα από SQL Server. • Το Visual Studio ενσωματώνει έναν εύχρηστο designer.
  • 83.
    Παράδειγμα using (NorthwindDataContext context =new NorthwindDataContext()) { var customers = from c in context.Customers where(c.ContactName.Contains( textBoxCustomerName.Text.Trim()) && c.CompanyName.Contains(textBoxCompanyName.Text.Trim())) select c; gridViewCustomers.DataSource = customers; gridViewCustomers.DataBind(); }
  • 84.
    LINQ To XML •Με το LINQ To XML μπορούμε εύκολα να επεξεργαστούμε αρχεία XML – Ακόμα και HTML, αν είναι valid! • Ενώ υπάρχει στο .ΝΕΤ δυνατότητα για χρήση XML DOM αλλά και το XQuery, το LINQ To XML είναι πιο φιλικό στον προγραμματιστή
  • 85.
    Ένα αρχείο XML <?xmlversion="1.0" encoding="utf-8" ?> <Tutorials> <Tutorial> <Author>The Reddest</Author> <Title> Creating an XP Style WPF Button with Silverlight </Title> <Date>2/20/2008</Date> </Tutorial> <Tutorial> <Author>The Fattest</Author> <Title> Flex And Yahoo Maps </Title> <Date>2/12/2007</Date> </Tutorial> <Tutorial> <Author>The Tallest</Author> <Title> WPF Tutorial - Creating A Custom Panel Control </Title> <Date>2/18/2008</Date> </Tutorial> </Tutorials>
  • 86.
    Parsing με LINQTo XML XDocument xmlDoc = XDocument.Load("TestFile.xml"); var tutorials = from tutorial in xmlDoc.Descendants("Tutorial") select new { Author = tutorial.Element("Author").Value, Title = tutorial.Element("Title").Value, Date = tutorial.Element("Date").Value, };
  • 87.
    Reflection Οι Managed εφαρμογέςαναπτύσσονται σε assemblies που περιέχουν πολλαπλά αρχεία και μπορούν να περιέχουν πολλαπλά modules με managed ή unmanaged κώδικα. Τα managed modules περιέχουν metadata (~ επιπλέον, συνήθως περιγραφικές, πληροφορίες) που περιγράφουν το περιεχόμενο τους και τις δομές δεδομένων μέσα σε κάτι που καλείται «manifest». Αυτές οι πληροφορίες μπορούν να ανακτηθούν χρησιμοποιώντας το ILDASM, ή μέσω των classes που εφαρμόζονται μέσα στο System.Reflection namespace. Στο .ΝΕΤ, reflection σημαίνει έλεγχος του metadata για την ανάκτηση πληροφοριών για ένα assembly, ένα module ή ένα type. Το Visual Studio, π.χ., χρησιμοποιεί το reflection για την ανάκτηση Intellisense Data.
  • 88.
    Assemblies, Modules καιTypes Υπάρχουν τρία σχετικά namespaces: System.Reflection.Assembly System.Reflection.Module System.Type Το πρόγραμμα asminfo.cs που ακολουθεί, δείχνει πως το Reflection χρησιμοποιείται για την ανάκτηση πληροφοριών για ένα αρχείο file.dll. Παρατηρήστε τη χρήση των ακόλουθων τύπων: • Assembly • AssemblyName • Version • Module[ ] • Type[ ] • AssemblyName[ ]
  • 89.
    asmInfo.cs class MyApp { staticvoid Main (string[] args) { if (args.Length == 0) { Console.WriteLine ("Error: Missing file name"); return; } try { Assembly a = Assembly.LoadFrom (args[0]); AssemblyName an = a.GetName (); byte[] bytes = an.GetPublicKeyToken (); if (bytes == null) Console.WriteLine ("Naming: Weak"); else Console.WriteLine ("Naming: Strong"); Version ver = an.Version; Console.WriteLine ("Version: {0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision); Console.WriteLine ("nModules"); Module[] modules = a.GetModules (); foreach (Module module in modules) Console.WriteLine (" " + module.Name); Console.WriteLine ("nExported Types"); Type[] types = a.GetExportedTypes (); foreach (Type type in types) Console.WriteLine (" " + type.Name); Console.WriteLine ("nReferenced Assemblies"); AssemblyName[] names = a.GetReferencedAssemblies (); foreach (AssemblyName name in names) Console.WriteLine (" " + name.Name); } catch (Exception e) { Console.WriteLine (e.Message); } } } Εφαρμοσμένα ως collections
  • 90.
    Χρήση pointers απόC# • Η C# μας επιτρέπει να γράψουμε "unsafe" κώδικα. • Ο Unsafe κώδικας δεν τρέχει κάτω από το memory management του Common Language Runtime (CLR). • Οι Pointers είναι σαν τα references στη C# (MyObject x = new MyObject()). • Η κύρια διαφορά είναι ότι ο δείκτης μπορεί να δείξει οπουδήποτε στη μνήμη • Για να μεταγλωτιστεί unsafe κώδικας, πρέπει να γίνει χρήση της επιλογής /unsafe στον compiler.
  • 91.
    Παράδειγμα unsafe { int* fib =stackalloc int[100]; int* p = fib; *p++ = *p++ = 1; for (int i = 2; i < 100; ++i, ++p) *p = p[-1] + p[-2]; for (int i = 0; i < 10; ++i) Console.WriteLine(fib[i]); }
  • 92.
    Attributes Μπορούμε να φανταστούμετις attributes ως τρόπους να “διακοσμήσουμε” ή να καθορίσουμε λεπτομέρειες γύρω από μια δήλωση στον κώδικα μας. Για παράδειγμα, τα access modifiers μιας class (public, protected, private) είναι attributes. Οι attributes του SDK μπορούν να βρεθούν χρησιμοποιώντας το namespace System.Reflection.{AssemblyConfigurationName, AssemblyCultureName, …}. Η C# μας δίνει την δυνατότητα να ορίσουμε attributes στο επίπεδο του assembly, module, class, struct, interface, enum, delegate, method, parameter, field, property (indexer, getter, setter), event (field, property, add, remove). Αυτό είναι δυνατόν γιατί υπάρχουν τρεις classes των attributes: AttributeUsage, Conditional, and Obsolete.
  • 93.
    Attributes, μέρος 2 ΟιAttributes είναι δηλώσεις κώδικα που προστίθενται για να προσδιορίσουν ή να ανακτήσουν πληροφορίες για metadata. Αν χρησιμοποιηθούν έξυπνα, οι δηλώσεις attribute μπορούν να αποδειχτούν ένα εξαιρετικό εργαλείο για τον ομαδικό προγραμματισμό και για τη διαχείριση των εκδόσεων (version control). Μια attribute εφαρμόζεται στο κομμάτι κώδικα που βρίσκεται αμέσως μετά από τη δήλωση της: using System.Diagnostics; [Conditional ("DEBUG")] public void DoStuff () { ... } Αυτό καλείται «δώσιμο μιας attribute σε μια μέθοδο». Αν ο κώδικας γίνει compiled χωρίς ένα “DEBUG” σύμβολο, ένα token τοποθετείται στο metadata για να υποδηλώσει ότι το DoStuff δε θα κληθεί. Αν κάποιος άλλος κώδικας καλέσει το DoStuff σε release mode, η κλήση θα αγνοηθεί. Το DoStuff θα εκτελεστεί μόνο αν το module του γίνει compiled σε DEBUG mode.
  • 94.
    Χρήση Attributes γιαVersion Control [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] class CodeRevisionAttribute : Attribute { public string Author; public string Date; public string Comment; public CodeRevisionAttribute (string Author, string Date) { this.Author = Author; this.Date = Date; } } Ο κώδικας μπορεί να χρησιμοποιηθεί ως εξής: [CodeRevision ("billg", "07-19-2001")] [CodeRevision ("steveb", "09-30-2001", Comment="Fixed Bill's bugs")] struct Point { public int x; public int y; public int z; } Ο compiler προσθέτει την Attribute
  • 95.
    MemberInfo info =typeof (Point); object[] attributes = info.GetCustomAttributes (false); if (attributes.Length > 0) { Console.WriteLine ("Code revisions for Point struct"); foreach (CodeRevisionAttribute attribute in attributes) { Console.WriteLine ("nAuthor: {0}", attribute.Author); Console.WriteLine ("Date: {0}", attribute.Date); if (attribute.Comment != null) Console.WriteLine ("Comment: {0}", attribute.Comment); } } Code revisions for Point struct Author: billg Date: 07-19-2001 Author: steveb Date: 09-30-2001 Comment: Fixed Bill's bugs Χρήση Attributes για Version Control, μέρος 2 Πληροφορίες από τη Attribute
  • 96.
    Το Dynamic Loading(δυναμική φόρτωση) αναφέρεται στη διαδικασία εισαγωγής modules (τυπικά από .dll αρχεία) όταν χρειάζονται. Τα Plug-ins είναι ένα καλό παράδειγμα του dynamic loading. Το Dynamic Loading πραγματοποιείται χρησιμοποιώντας μια τεχνική που λέγεται “Late Binding”, που ουσιαστικά γίνεται με την αναβολή της ανάθεσης των τύπων (type assignment) ενός καινούργιου object μέχρι να χρειαστούν πληροφορίες για τους τύπους (για να πάρουμε τα μέλη τους, το μέγεθος τους, κ.τ.λ.). Το Reflection κάνει το Late Binding για το Dynamic Loading δυνατόν. Late Binding
  • 97.
    Threading • Μπορούμε ναχρησιμοποιήσουμε το namespace System.Threading για τη δημιουργία πολυνηματικών εφαρμογών • Χρειάζεται ένας delegate ThreadStart ή ParameterizedThreadStart (αν θέλουμε παραμέτρους) • Δημιουργία αντικειμένου Thread, με τον αντίστοιχο delegate στον constructor • Εκκίνηση του thread, με την threadInstance.Start()
  • 98.
    Παράδειγμαstatic void Main(string[]args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(WriteToConsole); Console.WriteLine("In parent thread, managed thread id = {0} and child thread id = {1}", Thread.CurrentThread.ManagedThreadId, t.ManagedThreadId); t.Start(); } Console.ReadLine(); } readonly static Random random = new Random(DateTime.Now.Millisecond); static void WriteToConsole() { Thread.Sleep(random.Next(500,3000)); Console.WriteLine("In child thread, Time is {0} and ThreadID is {1}",DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId); }
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
    Σας ευχαριστώ  Console.WriteLine(newFunc<string> (() => "Ερωτήσεις - Συζήτηση").Invoke()); //output: Ερωτήσεις - Συζήτηση “True programming languages use curly brackets” Anonymous, 2007

Editor's Notes

  • #2 Σε αυτή την παρουσίαση θα μιλήσουμε σχετικά με το .ΝΕΤ Framework και τη γλώσσα C#.
  • #3 Επισκόπηση περιεχομένων
  • #5 Το .ΝΕΤ Framework είναι μια ολοκληρωμένη πλατφόρμα ανάπτυξης και εκτέλεσης λογισμικού
  • #7 Η πρώτη έκδοση του .ΝΕΤ ήταν το 2002, με το .ΝΕΤ 1.1 Το 2003 κυκλοφόρησε η έκδοση 1.1, με μικρές αναβαθμίσεις σε σχέση με την αρχική έκδοση. Το .ΝΕΤ ουσιαστικά «ωρίμασε» το 2005, με την έκδοση 2.0 Μπορείτε να δείτε εδώ http://en.wikipedia.org/wiki/.NET_Framework_version_list για μια περιγραφή των εκδόσεων του .ΝΕΤ
  • #8 Στο κέντρο βλέπουμε ότι βρίσκεται το λειτουργικό, το οποίο ουσιαστικά τρέχει πάνω στο hardware. Με την έλευση του .ΝΕΤ, οι εφαρμογές που εκτελούνται κάτω από το .ΝΕΤ λέγονται managed, ενώ οι υπόλοιπες λέγονται unmanaged. Managed εφαρμογές είναι οι εφαρμογές που είναι γραμμένες σε κάποια γλώσσα του .ΝΕΤ. Επίσης, κατά την εκτέλεσή τους διαχειρίζονται από την υποδομή του .ΝΕΤ, το CLR (Common Language Runtime), οπότε υπάρχουν οι ευκολίες της αυτόματης διαχείρισης μνήμης, εξαιρέσεων (Exceptions), ασφάλεια κ.λ.π. Επίσης, οι managed εφαρμογές δεν μεταγλωττίζονται κατευθείαν σε γλώσσα μηχανής, αλλά σε μια ενδιάμεση γλώσσα, την IL (Intermediate Language). Η μεταγλώττιση της IL σε γλώσσα μηχανής (ώστε να μπορεί να εκτελεστεί η εφαρμογή) γίνεται κατά την εκτέλεση της εφαρμογής. Unmanaged εφαρμογές είναι οι εφαρμογές που είναι γραμμένες σε C,C++, VB6 (κ.α.) και δεν εκτελούνται κάτω από την ‘επίβλεψη’ του .ΝΕΤ Framework.
  • #9 Το .ΝΕΤ σχεδιάστηκε με γνώμονα τα παρακάτω χαρακτηριστικά Interoperability Λόγω της πληθώρας των ‘παλιών’ εφαρμογών και βιβλιοθηκών που υπάρχουν, το .ΝΕΤ κάνει έυκολη την πρόσβαση σε components που εκτελούνται εκτός του .ΝΕΤ Framework. Πρόσβαση σε COM components είναι δυνατή μέσω κλάσεων στο System.Runtime.InteropServices και System.EnterpriseServices. Πρόσβαση σε άλλες λειτουργικότητες είναι δυνατή μέσω του χαρακτηριστικού P/Invoke Common Language Runtime Το Common Language Runtime είναι μια εικονική μηχανή μέσα στο .ΝΕΤ Framework. Όλα τα .ΝΕΤ προγράμματα εκτελούνται κάτω από την επίβλεψη του CLR, το οποίο εγγυάται διάφορες ιδιότητες και συμπεριφορές στις περιοχές της διαχείρισης μνήμης, ασφάλειας και διαχείριση εξαιρέσεων. Γλωσσική ανεξαρτησία Το .ΝΕΤ συμπεριλαμβάνει ένα κοινό σύστημα τύπων (Common Type System). Ο ορισμός του CTS ορίζει όλους τους πιθανούς τύπους δεδομένων και όλες τις προγραμματιστικές δομές που υποστηρίζονται από το CLR και το πως μπορούνε να αλληλεπιδράσουν μεταξύ τους. Εξαιτίας αυτού του χαρακτηριστικού, το .ΝΕΤ υποστηρίζει την ανταλλαγή στιγμιότυπων (instances) μεταξύ προγραμμάτων γραμμένα σε οποιαδήποτε από τις .ΝΕΤ γλώσσες. Base Class Library Το Base Class Library, μέρος του Framework Class Library είναι με βιβλιοθήκη με λειτουργικότητα διαθέσιμη σε όλες τις γλώσσες που μπορούνται να εκτελεστούν κάτω από το .ΝΕΤ Framework. Το BCL παρέχει κλάσεις που περιλαμβάνουν έναν αριθμό διάφορων λειτουργιών, όπως ανάγνωση και εγγραφή σε αρχεία, σχεδιασμός γραφικών, συναλλαγές με βάσεις δεδομένων, χειρισμός εγγράφου XML κ.α. Απλοποιημένη εγκατάσταση Το .NET περιλαμβάνει μηχανισμούς και εργαλεία που βοηθούν την διαχείριση της εγκατάστασης λογισμικού. Ασφάλεια Το .ΝΕΤ σχεδιάστηκε με βάση την προστασία από buffer overflows. Επίσης, παρέχει ένα μοντέλο ασφαλείας/προστασίας για κάθε είδους εφαρμογές. Φορητότητα Ο σχεδιασμός του .ΝΕΤ του επιτρέπει να είναι θεωρητικά platform-agnostic, και επομένως συμβατό ανάμεσα σε διάφορες πλατφόρμες.
  • #10 Το Common Language Infrastructure (CLI) είναι ένα ανοιχτό πρότυπο που έχει αναπτυχθεί από τη Microsoft και περιγράφει τον εκτελέσιμο κώδικα αλλά και το περιβάλλον εκτέλεσης που σχηματίζουν τον πυρήνα του .ΝΕΤ Framework. Το πρότυπο προσδιορίζει ένα περιβάλλον που επιτρέπει σε πολλαπλές γλώσσες υψηλού επιπέδου να χρησιμοποιηθούν σε διαφορετικές υπολογιστικές πλατφόρμες χωρίς να χρειάζεται να ξαναγραφούν/επαναμεταγλωττιστούν για συγκεκριμένες αρχιτεκτονικές. Το CLI περιγράφει τις παρακάτω λειτουργίες Common Type System (CTS) Ένα σύνολο από τύπους δεδομένων και λειτουργίες που μοιράζονται από όλες τις CTS-συμβατές γλώσσες. Metadata Οι πληροφορίες για την δομή του προγράμματος/βιβλιοθήκης είναι ανεξάρτητες της γλώσσας προγραμματισμού έτσι ώστε να μπορούν να είναι ορατές από άλλες γλώσσες και εργαλεία, επιτυγχάνοντας την επαναχρησιμοποίηση μεταγλωττισμένου κώδικα ο οποίος μπορεί να είναι γραμμένος σε διαφορετική γλώσσα από την οποία εργαζόμαστε. Common Language Specification Ένα σύνολο κανόνων στους οποίους πρέπει να υπακούει κάθε γλώσσα που είναι γραμμένη για το CLI. Με αυτό τον τρόπο θα μπορεί να διαλειτουργήσει με άλλες CLS-συμβατές γλώσσες. Οι κανόνες του CLS προσδιορίζουν ένα υποσύνολο του CTS. Virtual Execution System Το VES φορτώνει και εκτελεί CLI-συμβατά προγράμματα χρησιμοποιώντας τα metadata, προκειμένου να συνδυάσει κομμάτια κώδικα γραμμένα σε διαφορετικές γλώσσες, κατά την εκτέλεση των προγραμμάτων.
  • #11 Το Common Type System είναι ένα standard που προσδιορίζει πως οι ορισμοί των τύπων (Types) και οι τιμές των τύπων αυτών αναπαρίστανται στη μνήμη του υπολογιστή. Έχει σαν σκοπό να επιτρέπει σε προγράμματα που είναι γραμμένα σε διαφορετικές γλώσσες προγραμματισμού να μπορούν να αλληλεπιδρούν χωρίς προβλήματα. Λειτουργίες Η σύσταση μιας πλατφόρμας που βοηθάει στην αλληλεπίδραση μεταξύ διαφορετικών γλωσσών προγραμματισμού (cross-language integration) Η παροχή ενός αντικειμενοστρεφούς μοντέλου που υποστηρίζει την υλοποίηση μιας πληθώρας διάφορων γλωσσών προγραμματισμού Ο ορισμός κανόνων που πρέπει να ακολουθούν οι γλώσσες προγραμματισμού, το οποίο στηρίζει την επικοινωνία διαφορετικών τύπων αυτών των γλωσσών Το CTS ακόμα ορίζει τους κανόνες που ορίζουν την μεταφορά δεδομένων από τη μία γλώσσα στην άλλη Οι γλώσσες που υποστηρίζουν το .ΝΕΤ μπορούν να υλοποιούν όλες ή τις πιο κοινές δομές δεδομένων Κατηγορίες Τύπων To CTS υποστηρίζει δύο γενικές κατηγορίες τύπων Value Types Οι value types περιέχουν τα δεδομένα τους, και instances των value types τοποθετούνται στη στοίβα μνήμης του προγράμματος είτε τοποθετούνται inline στη δομή που τους περιέχει. Οι value types μπορεί να είναι έτοιμοι (υποστήριξη από τη γλώσσα), προσδιορισμένοι από το χρήστη (struct) ή απαριθμήσεις (enumerations). Reference Types Οι reference types περιέχουν μία αναφορά (reference) στην θέση μνήμης που έχουν αποθηκευτεί τα δεδομένα του. Τα δεδομένα των reference types αποθηκεύονται στον σωρό μνήμης του προγράμματος. Reference types μπορεί να είναι κλάσεις, δείκτες (pointers) ή interfaces. Τύποι κλάσεων περιλαμβάνουν αυτές που έχουνε γραφεί από developers, boxed value types ή delegates. Boxing και Unboxing Η μετατροπή ενός value type σε reference type λέγεται boxing. Παράδειγμα: int x = 5; object y = x; //boxing Το αντίθετο, δηλαδή η μετατροπή από έναν reference type (που έχει αποθηκεύσει ένα value type) σε value type λέγεται unboxing. Παράδειγμα: int x = 5; object y = x; //boxing int z = (int)y; //unboxing – απαραίτητο casting Αξίζει να αναφερθεί ότι τόσο το boxing όσο και το unboxing είναι σχετικά ακριβές διαδικασίες από άποψη απόδοσης, μιας περιλαμβάνουν μεταφορά δεδομένων από στοίβα στο σωρό (και αντιστρόφως).
  • #13 Για περισσότερες γλώσσες, μπορείτε να δείτε το http://www.dotnetpowered.com/languages.aspx Η Microsoft υποστηρίζει επίσημα διάφορες γλώσσες, τις C#, την Visual Basic, την F#, την IronRuby και την IronPython
  • #15 Όταν μεταγλωττίζουμε ένα project γραμμένο σε κάποια γλώσσα του .ΝΕΤ, τότε αυτό δεν μεταγλωττίζεται σε κώδικα μηχανής (native code). Αντιθέτως, μεταγλωττίζεται σε μια αντικειμενοστρεφή/assembly-like γλώσσα που ονομάζεται IL (Intermediate Language).
  • #16 Πλεονεκτήματα των application domains Λιγότερο κόστος σε απόδοση καθώς πολλά application domains μπορούν να εκτελούνται μέσα στην ίδια διεργασία (process). Εξάλλου, η δημιουργία καινούριας διεργασίας από το λειτουργικό είναι αρκετά κοστοβόρα σε απόδοση. Μπορούμε να σταματήσουμε την εκτέλεση ενός application domain χωρίς να σταματήσουμε την εκτέλεση ενός άλλου μέσα στο ίδιο process Ένα σφάλμα ή μια εξαίρεση (exception) σε ένα application domain δεν θα επηρεάσει την εκτέλεση άλλων application domains μέσα σε μια διεργασία Μπορούμε να ορίσουμε παραμέτρους για ένα συγκεκριμένο application domain, χωρίς να επηρεάσουμε άλλα application domains μέσα στην ίδια διεργασία Κάθε application domain μέσα σε μια διεργασία μπορεί να έχει διαφορετικές ρυθμίσεις ασφαλείας Κώδικας μέσα σε ένα application domain δεν μπορεί απευθείας να έχει πρόσβαση σε κώδικα ενός άλλου application domain, ακόμα κι αν εκτελούνται μέσα στην ίδια διεργασία
  • #19 Το τελευταίο bullet δεν είναι γενικολογία, καθώς πάρα πολλά software προϊόντα και υπηρεσίες πλέον κάνουν expose API σε .ΝΕΤ
  • #30 http://www.albahari.com/valuevsreftypes.aspx
  • #31 Όταν περνάμε μια τιμή σε μια συνάρητηση χωρίς κάποιο keyword, τότε η τιμή παραμένει αμετάβλητη μετά την εκτέλεση της συνάρτησης. Παράδειγμα, έστω ότι έχουμε την ακόλουθη συνάρτηση void Increase(int x) { x += 1; } Και την καλέσουμε ως εξής int y = 6; Increase(y); Console.WriteLine(y); Τότε η τιμή του y μετά την εκτέλεση της Increase θα παραμείνει 6. Αυτό γιατί περνάμε την τιμή χωρίς κάποιο ειδικό keyword, δηλαδή την περνάμε by value (κατά αξία). Με αυτό τον τρόπο, στη συνάρτηση δεν μεταφέρεται πρόσβαση στο χώρο μνήμης που της μεταβλητής, αλλά ένα ακριβές αντίγραφο της τιμής της. Οπότε και ενδεχόμενη αλλαγή τιμής μέσα στη συνάρτηση δεν διατηρείται μετά την εκτέλεση της συνάρτησης. Σε αντίθετη περίπτωση, αν θέλουμε να επιτύχουμε διατήρηση της τιμής, πρέπει να χρησιμοποιήσουμε το ref keyword. Για παράδειγμα, void Swap(ref int a, ref int b) { int temp = a; a = b; b = temp; } Και να την καλέσουμε ως εξής int x = 7; int y = 9; Swap(ref x, ref y); Console.WriteLine(“x = {0}, y = {1}”); //output: x = 9, y = 7 Θα παρατηρήσετε ότι την λέξη ref την χρησιμοποιούμε και κατά την κλήση της συνάρτησης (αν δεν το κάνουμε, ο compiler θα επιστρέψει error). Αυτό γίνεται για να είναι φανερό σε όποιον διαβάζει τον κώδικα ότι οι συγκεκριμένες μεταβλητές θα περαστούν by reference, δηλαδή η τιμή που θα τους ανατεθεί μέσα στην συνάρτηση θα διατηρηθεί και μετά το πέρας της εκτέλεσής της.
  • #36 Οι δομές (structures) θεωρούνται ιδανικές για τύπους δεδομένων μέχρι και 16 bytes, για αυτό και τα συναντάμε σε γεωμετρικούς τύπους δεδομένων (π.χ. Location)
  • #49 An iterator is a method, get accessor, or operator that performs a custom iteration over an array or collection class by using the yield keyword. The yield return statement causes an element in the source sequence to be returned immediately to the caller before the next element in the source sequence is accessed. Although you write an iterator as a method, the compiler translates it into a nested class that is, in effect, a state machine. This class keeps track of the position of the iterator as long the foreach loop on the client code continues. An iterator is invoked from client code by using a foreach statement. For example, you can create an iterator for a class that returns the elements in reverse order, or that performs an operation on each element before the iterator returns it. When you create an iterator for your class or struct, you do not have to implement the whole IEnumerator interface. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerator or IEnumerator<(Of <(T>)>) interface.
  • #50 Σε πάρα πολλές περιπτώσεις χρειάζεται να τοποθετήσουμε την τιμή null σε value types. Κλασσικό παράδειγμα, η πρόσβαση σε βάση δεδομένων. Ας υποθέσουμε ότι έχουμε μια εφαρμογή η οποία ζητάει από το χρήστη να πληκτρολογήσει την ηλικία του, χωρίς όμως αυτό να είναι υποχρεωτικό. Πριν το .ΝΕΤ 2, η συνήθης τακτική ήταν να έχουμε δύο properties στην κλάση στην οποία υπήρχε η ιδιότητα ηλικία. Ένα property που καταχωρούσαμε την ηλικία, π.χ. int Age, και ένα property για αν το Age έχει value, π.χ. bool AgeHasValue. Τότε, όταν κάναμε query στην βάση για την ηλικία και υπήρχε τιμή null, βάζαμε στο AgeHasValue την τιμή false. Σε αντίθετη περίπτωση, βάζαμε στο Age την ηλικία από την βάση και στο AgeHasValue την τιμή true. Όπως καταλαβαίνουμε, αν είχαμε πολλά τέτοια προαιρετικά πεδία τότε η κλάση μας θα γινόταν αρκετά μεγάλη. Το πρόβλημα αυτό λύθηκε με την έλευση του .ΝΕΤ 2. Με τα nullable types, μπορούμε να καταχωρήσουμε την τιμή null σε οποιοδήποτε value type δηλωθεί με ένα ερωτηματικό μετά τον τύπο του. Για παράδειγμα, έναν nullable int τον δηλώνουμε ως int? (είναι ακριβώς το ίδιο με το να γράψουμε Nullable<int>). Το Nullable<T> έχει δύο πολύ χρήσιμα properties, το HasValue και το Value. Το πρώτο είναι τύπου boolean και επιστρέφει true αν και μόνο αν ο value type έχει τιμή διάφορη του null. Το δεύτερο μας επιστρέφει την τιμή του nullable type (θα πρέπει να έχει προηγηθεί έλεγχος αν το HasValue είναι true, ειδάλλως θα χτυπήσει Exception). Παράδειγμα int? x; int y; x = null; x = 5; if(x.HasValue) y = x.Value;
  • #59 Option 1. Inherit the class and then implement the functionality in an instance method in the derived class. Option 2. Implement the functionality in a static method added to a helper class. Option 3. Use aggregation instead of inheritance.
  • #60 The major difference between calling extension methods and calling static helper methods is that static methods are called in prefix notation, whereas extension methods are called in infix notation. The latter leads to more readable code when the result of one operation is used for another operation.
  • #66 1.3 LINQ providers 1.3.1 LINQ to Objects 1.3.2 LINQ to XML 1.3.3 LINQ to SQL 1.3.4 LINQ to DataSets 1.3.5 Other providers