Implicit και explicit μετατροπή τύπων στη C Sharp είναι όροι που αναφέρονται στον τρόπο με τον οποίο μπορούμε να αλλάξουμε τον τύπο των δεδομένων που χρησιμοποιούνται από ένα πρόγραμμα. Ο τρόπος που επιλέγεται κάθε φορά επιλέγεται λαμβάνοντας υπ’ όψιν τον αρχικό και τον επιθυμητό τύπο μετατροπής, καθώς και τη σχέση μεταξύ τους.
Στη C#, αφού κάποια μεταβλητή έχει δηλωθεί, δεν μπορεί να δηλωθεί εκ νέου ή να χρησιμοποιηθεί για την αποθήκευση δεδομένων διαφορετικού τύπου από τον δηλωθέντα. Για παράδειγμα, εφόσον δηλώσουμε μία μεταβλητή ακεραίου τύπου με το όνομα n, δεν μπορούμε να εκχωρήσουμε σε αυτήν δεδομένα τύπου συμβολοσειράς, πχ τη λέξη world. Το πρόγραμμα αντιμετωπίζει μία αντίφαση, η οποία δεν του επιτρέπει να ολοκληρώσει το compilation. Το ακόλουθο παράδειγμα επιδεικνύει αυτήν την αντίφαση:
int n; n= "world";
Παρ’ όλα αυτά, κάποιες φορές χρειάζεται να αντιγράψουμε μία τιμή σε μεταβλητή διαφορετικού τύπου ή να την περάσουμε ως παράμετρο σε μέθοδο με ορίσματα διαφορετικού τύπου. Ενδεικτική περίπτωση αποτελεί η ανάγκη να μεταφέρουμε την τιμή μίας μεταβλητής ακεραίου τύπου σε μέθοδο που δέχεται όρισμα με υποδιαστολή (double). Οι διαδικασίες της μετατροπής από έναν τύπο δεδομένων σε κάποιο διαφορετικό τύπο αναφέρονται ως type conversions. Στη γλώσσα προγραμματισμού C#, διακρίνονται οι ακόλουθοι τύποι μετατροπής: implicit conversion και explicit conversion.
Implicit και explicit μετατροπή τύπων στη C Sharp: implicit conversion
Ο τρόπος αυτός επιλέγεται όταν η μετατροπή είναι ασφαλής και δε χάνεται κανένα τμήμα της πληροφορίας, δηλαδή όταν η τιμή της μεταβλητής μεταφέρεται αυτούσια στη νέα μεταβλητή. Στην περίπτωση αυτή, δεν απαιτείται ειδική σύνταξη για τη διαδικασία μετατροπής. Ενδεικτικά παραδείγματα αποτελούν η μετατροπή από ακέραιο μικρότερης σε ακέραιο μεγαλύτερης χωρητικότητας , πχ. Int16 σε Int64. καθώς και η μετατροπή αντικειμένων παράγωγων κλάσεων σε αντικείμενα της γονικής τους κλάσης. Για τους υπάρχοντες αριθμητικούς τύπους, το implicit conversion μπορεί να πραγματοποιηθεί επιτυχώς, όταν η τιμή προς μετατροπή δεν πρόκειται να αλλοιωθεί ή να χάσει τμήμα της πληροφορίας, πχ να στρογγυλοποιηθεί προς τα κάτω.
Για παράδειγμα, μία μεταβλητή τύπου long (8 byte) μπορεί να αποθηκεύσει οποιαδήποτε τιμή ακέραιας μεταβλητής int κανονικού μεγέθους (4 bytes σε υπολογιστή 32-bit). Στο παράδειγμα που ακολουθεί, ο compiler πραγματοποιεί τη μετατροπή της τιμής σε long πριν εκχωρήσει την τιμή στη μεταβλητή myLongNumber:
int myNumber = 83647; long myLongNumber = myNumber;
Το ακόλουθο παράδειγμα είναι ενδεικτικό της περίπτωσης των κλάσεων. Το implicit conversion πραγματοποιείται επιτυχώς για τη μετατροπή αντικειμένου παράγωγης κλάσης προς τη γονική (βάση) της. Οι παράγωγες κλάσεις περιέχουν πάντα τα μέλη του γονέα, οπότε δεν απαιτείται ιδιαίτερη σύνταξη για τη μετατροπή:
BaseClass myBase; ChildClass myChild = new ChildClass(); myBase = myChild;
Implicit και explicit μετατροπή τύπων στη C Sharp: explicit conversion
Ο τρόπος αυτός αναφέρεται και ως casting. Το casting κρίνεται απαραίτητο, όταν τμήμα της πληροφορίας πρόκειται να χαθεί ή ακόμα όταν η μετατροπή ενδέχεται να αποτύχει για άλλους λόγους. Τυπικό παράδειγμα αποτελεί η αριθμητική μετατροπή σε τύπο χαμηλότερης ακριβείας από τον αρχικό ή η μετατροπή αντικειμένου μίας γονικής κλάσης σε αντικείμενο παράγωγης.
Σε κάθε περίπτωση κατά την οποία η (μερική) απώλεια πληροφορίας είναι αναπόφευκτη, ο compiler χρειάζεται να γνωρίζει ότι πρόκειται να πραγματοποιήσει ένα explicit conversion, επομένως απαιτείται ένας cast operator. Η διαδικασία προϋποθέτει συγκεκριμένη σύνταξη που θα ενημερώνει τον compiler ότι ο συντάκτης του κώδικα είναι ενήμερος για το ενδεχόμενο. Το casting αποτελεί στην ουσία μία ειδοποίηση προς τον compiler. Για τη σύνταξη, χρειάζεται να γραφεί ο επιθυμητός τύπος μετατροπής μέσα σε παρενθέσεις, πριν τη σύνταξη της τιμής που θα μετατραπεί. Το ακόλουθο παράδειγμα παρουσιάζει τη μετατροπή τιμής τύπου double σε τιμή τύπου int. Το πρόγραμμα δεν θα προχωρήσει σε compile χωρίς αυτή τη σύνταξη.
static void Main() { double beforeConversion = 43.9; int afterConversion; afterConversion = (int) beforeConversion; Console.WriteLine(afterConversion); }
Το αποτέλεσμα που έχουμε στην οθόνη είναι το εξής:
43
Το ακόλουθο παράδειγμα είναι ενδεικτικό της περίπτωσης των κλάσεων. Το implicit conversion δεν πραγματοποιείται επιτυχώς για τη μετατροπή αντικειμένου γονικής κλάσης προς αντικείμενο μίας παράγωγης. Όπως προαναφέρθηκε, οι παράγωγες κλάσεις περιέχουν πάντα τα μέλη του γονέα, αλλά ο γονέας δεν περιέχει πάντα όλα τα μέλη της παράγωγης. Κατά την εκχώρηση, θα χρειαστεί να εκχωρηθούν στο αντικείμενο της παράγωγης κλάσης ιδιότητες που δεν υπάρχουν στη γονική. Επομένως απαιτείται ιδιαίτερη σύνταξη cast για τη μετατροπή, όπως φαίνεται παρακάτω:
BaseClass myBase; ChildClass myChild = new ChildClass(); myBase = myChild; ChildClass mySecondChild = (ChildClass) myBase;
Εάν η σύνταξη αυτή δε χρησιμοποιηθεί, το πρόγραμμα προχωρά κανονικά σε κατάσταση compile mode. Το σφάλμα όμως προκύπτει κατά το runtime και εφόσον η δεξιά τιμή μετά τον τελεστή εκχώρησης δεν ανήκει στον τύπο της παράγωγης κλάσης. Η λειτουργία του cast δεν έγκειται στην ουσιαστική μετατροπή του αρχικού αντικειμένου, αλλά στην αξιοποίηση συγκεκριμένης τμηματικής πληροφορίας αυτού. Εφόσον ο compiler λάβει την πληροφορία μέσω αυτής της σύνταξης, τότε το πρόγραμμα εκτελείται κανονικά χωρίς κανένα exception.