Προς το περιεχόμενο

Ερωτήσεις για C#


migf1

Προτεινόμενες αναρτήσεις

  • Απαντ. 51
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Το ξερω οτι εισαι ξεροκεφαλος σε μερικα θεματα, αλλα θα στο πω. Βαλε vs ή κατι που να εχει intelliSense, αλλιως απλα παρατα τα.

 

Εντάξει νομίζω είναι λίγο υπερβολικό να του ζητάς να τα παρατήσει διαφορετικά.

 

Κι εγώ το βρίσκω εντελώς χαμένο κόπο και εφιαλτικά αργό να γράφεις C# σε notepad++ οταν δίπλα σου κάθεται το vs και σκονίζεται και θα μπορούσα να επιχειρηματολογήσω ώρες στο γιατι το πιστεύω αλλά στην τελική ο κάθε ένας είναι ελεύθερος να κάνει ο,τι και όπως θέλει.

 

Ακόμα και αν αυτό που κάνει του αυξάνει τις πιθανότητες να πάρει εντελώς λειψή εικόνα της πλατφόρμας ή ακόμα να κουραστεί και να τα παρατήσει ενώ αντίθετα κάτι τέτοιο θα είχε αποφευχθεί.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εγώ πάλι ρε παιδιά δεν καταλαβαίνω γιατί δεν μπορείτε να αποδεχτείτε πως ο κάθε άνθρωπος έχει διαφορετικούς κώδικες και μεθοδολογίες.

 

Θα μάθω τα βασικά της γλώσσας σε Notepad++, και όταν αρχίσω να ασχολούμαι με πιο advanced πράγματα τότε θα πάω σε κανονικό IDE. Θα 'ναι το VS Express, το SharpDevelop, το MonoDevelop, δεν το ξέρω ακόμα (προς το παρόν δεν με απασχολεί καν αυτό το θέμα).

 

 

 

Παρεμπιπτόντως, μια χαρά auto-completion engine έχει και το Notepad++ ...

 

post-38307-0-34112600-1353013974_thumb.jpg

 

αλλά το μόνο από τα provided xml που είναι 100% πλήρες είναι για την php και ακολουθούν C και C++ που περιέχουν τις περισσότερες από τις στάνταρ συναρτήσεις (ειδικά η C που έχει και λιγότερες).

 

Για C# δεν έχει ούτε μια συνάρτηση (την String.Split() και τα overlaod της εικόνας, τα έφτιαξα πρόχειρα εγώ) και δεν βρήκα να έχει φτιάξει κανείς (όπως π.χ. έχουν φτιάξει για lua, python, ακόμα και για Unity3d)

 

 

 

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Είμαι λίγο αναποφάσιστος για το αν θα πρέπει να ακολουθήσω τα στάνταρ της Microsoft ή του Mono. Βασικά είναι πολύ μεγάλη η ασυμβατότητα μεταξύ των runtimes τους (αν υπάρχει μεγάλος βαθμός συμβατότητας/portability μάλλον θα προτιμήσω να διαβάσω του Mono).

 

Περι ορέξεως... και μένα δε μου αρέσουν (και δεν ακολουθώ σε προσωπικό μου κώδικα) μερικά από τα guidelines της Microsoft (πχ braces on their own line σε ένα if της μίας γραμμής το θεωρώ υπερβολή), αλλά σαν σύνολο τις θεωρώ πολύ προτιμότερες από του Mono.

 

Την ασυμβατότητα μεταξύ των runtimes δε θα την έλεγα μεγάλη. Φυσικά τα τελευταία features πάντα έπονται του .NET αλλά overall δεν είναι κι άσχημα.

 

Επίσης, με την ευκαιρία που διάβασα τη σελίδα του Mono, βρίσκω την ευκαιρία να επισημάνω το εξής με το οποίο συμφωνώ παραπάνω από απόλυτα:

 

Performance and Readability

 

It is more important to be correct than to be fast.

It is more important to be maintainable than to be fast.

Fast code that is difficult to maintain is likely going to be looked down upon.

 

Αμήν.

 

Δεν ξέρω αν το πήρε το μάτι σου στις προηγούμενες σελίδες, που κάπου το ανέφερα, το σκεπτικό μου για αυτού του είδους την υλοποίηση των setters ήταν για να αποφορτίσω τους getters από τα συνεχόμενα calculations, μιας και οι getters χρησιμοποιούνται πολύ συχνότερα.

 

Αντιτίθεται αυτό το σκεπτικό με την κοινή πρακτική στη γλώσσα; Θεωρείται κακή πρακτική;

 

Εν συντομία, δύο λέξεις: "premature optimization"?

 

Γράφεις ένα πρόγραμμα της πλάκας που το χρησιμοποιείς για να μάθεις τα features της γλώσσας: το θεωρώ αστείο να μιλάμε για το performance των getters.

 

Γράφεις ένα σοβαρό εμπορικό πρόγραμμα στο οποίο οι getters αυτοί δεν χρησιμοποιούνται μέσα σε inner loop σε κάποιο CPU-bound τμήμα του προγράμματος: το θεωρώ λάθος και misguided να μιλάμε για το performance των getters.

 

Και πάμε άλλη μια φορά για εμπέδωση:

 

It is more important to be correct than to be fast.

It is more important to be maintainable than to be fast.

Fast code that is difficult to maintain is likely going to be looked down upon.

 

Τώρα, that said, δεν είναι κακή πρακτική από μόνο του το να κάνεις το calculation στον setter -- και γω αυτό έκανα στον κώδικα που είχα δώσει νωρίτερα. Κακή πρακτική είναι να το κάνεις αυτό εις βάρος της αναγνωσιμότητας του κώδικα.

 

Ή με άλλα λόγια: συμφωνώ με την ορθότητα της απόφασής σου, αλλά διαφωνώ (πολύ) με τον τρόπο που έφτασες σ' αυτή.

 

 

Μια ερώτηση: Κερδίζει κάτι κάποιος αν κάνει trivially implemented properties με private μεταβλητές αντί να κάνεις τις μεταβλητές public?

 

Μιλάω βέβαια μόνο για τέτοιο trivial implementation. Με την εξης λογική: Γιατί να μην κάνει απλά τη μεταβλητή public, και μετά αν αποφασίσει ότι θέλει να έχει πιο πολύ πολύπλοκη λογική να την κάνει property με το ίδιο όνομα. Έτσι ο κώδικας στις client classes δεν κάνει break.

 

Θα ξεκινήσω από το τέλος: κι όμως, ο κώδικας στις client classes θα κάνει break και μάλιστα με πολλούς τρόπους. Θα ήταν σωστότερο να πεις "αν κάνεις recompile τα sources των client classes, δε θα φας compilation error", αλλά και πάλι όχι 100% σωστό.

 

Βάλατε LinqPad που είπα παραπάνω? Ας δούμε αυτό το απλό πρόγραμμα:

 

>void Main()
{
var f = new Foo();
f.A = "hello";
f.B = "hello";
}

class Foo {
public string A { get; set; }
public string B;
}

 

Πατάμε κάτω στο output window εκεί που λέει "IL" και βλέπουμε την CIL που βγάζει ο compiler γι' αυτό τον κώδικα:

 

>
IL_0001: newobj	 UserQuery+Foo..ctor
IL_0006: stloc.0	
IL_0007: ldloc.0	
IL_0008: ldstr	 "hello"
IL_000D: callvirt UserQuery+Foo.set_A
IL_0012: nop		
IL_0013: ldloc.0	
IL_0014: ldstr	 "hello"
IL_0019: stfld	 UserQuery+Foo.B

 

 

Τι σημαίνουν αυτά τα instructions (δεν είναι απαραίτητο όμως για τη συνέχεια του post μου):

 

 

Οι stloc και ldloc (store/load αντίστοιχα) μεταφέρουν τιμές προς/από local variables (δηλαδή στο stack της process που τρέχει) στο ιδεατό stack της virtual machine του runtime. Οπότε, η newobj κάνει create ένα object και το βάζει στο CLR stack. H stloc.0 κάνει pop τον pointer σ' αυτό το object και τον γράφει στη local μεταβλητή f. Οι επόμενες 2 ld φορτώνουν τα ορίσματα για την callvirt που ακολουθεί, η οποία καλεί τον setter της property. Στο τέλος η αποθήκευση σε field γίνεται παρομοίως με την stfld.

 

 

 

Όπως είναι φανερό (αλλά και κατανοητό αν σκεφτεί κανείς ότι οι properties στην ουσία είναι methods), τελείως άλλο instruction χρησιμοποιείται στη μία περίπτωση και τελείως άλλο στην άλλη. Επομένως αν δεν κάνεις recompile τον client κώδικα και απλά πετάξεις τη νέα σου dll επάνω θα έχουμε πυροτεχνήματα.

 

Επιπλέον, τι γίνεται με τον κώδικα που κάνει reflection?

 

Ας πούμε π.χ. με το παραπάνω object f:

 

>Console.WriteLine(f.GetType().GetProperty("A").GetValue(f, null));

 

Αν αλλάξεις το property σε field (ή το αντίθετο αν έκανα reflect πάνω στο field) αυτός ο κώδικας απλά θα σκάσει με NullReferenceException at runtime. Θα το χαρακτήριζα λοιπόν με άνεση breaking change.

 

Τέλος υπάρχουν και άλλες πιο ψαγμένες ασυμβατότητες -- π.χ. μπορείς να κάνεις ref σε fields, αλλά όχι σε properties.

 

Τώρα, όσον αφορά το "τι να χρησιμοποιώ λοιπόν και με ποιό κριτήριο", τα έχει ήδη πει ο Jon Skeet οπότε πάω πάσο. Το ζουμί είναι στην ενότητα "The philosophical reason for only exposing properties".

 

Απαντήσεις σε μετέπειτα posts αργότερα, ήδη μάκρυνε πολύ αυτό το σεντόνι.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το σεντονάκι που χρωστούσα...

 

Thanks και για τον κώδικα! Κάτι παρόμοιο με τη χρήση του LINQ έχω βάλει ήδη στη input validation method, που απαιτεί μονάχα γράμματα ή blanks... αλλά βασικά κάπου την βρήκα σχεδόν έτοιμη, ψάχνοντας για κάτι άλλο. Οπότε την έβαλα παπαγαλίστικα, μέχρι να φτάσω να διαβάσω για το LINQ (ομοίως και για τα Rexeges... δεν έχω φτάσει ακόμα, τα σημείωσα όμως για να τα ξαναδώ όταν θα είμαι σε θέση να καταλαβαίνω και τα mechanics τους).

 

FYI ο κώδικας που παραθέτεις στην κλίμακα 1-10 παίρνει μετα βίας το 3 -- έχει μια ολόκληρη σειρά από χοντρά προβλήματα σχεδιασμού. Τελείως ενδεικτικά αναφέρω:

  1. Γενικά είναι κώδικας C γραμμένος με σύνταξη C#
  2. Έχει κατουρήσει στον τάφο της έννοιας του separation of concerns -- η ίδια method κάνει αποδοχή εισόδου, validation και επιστροφή τελικού αποτελέσματος
  3. To validation γίνεται με πολύ άσχημο τρόπο (ειδικά η επιλογή του error message...)
  4. Κάνει modify το this (γιατί? με ποιά λογική να μην είναι static και να επιστρέφει ένα καινούριο instance?) αλλά... το επιστρέφει κιόλας (εκτός συγκεκριμένων περιπτώσεων αυτό είναι τεράστιο red flag)

Πάντως και οι 2 κώδικες που μου έδωσες, έχουν το πρόβλημα πως αν υπάρχουν κολλητά blanks ανάμεσα στα tokens, τότε προστίθενται ως κενά. Πριν λίγο ανακάλυψα μια overloaded έκδοση της split η οποία δέχεται ως 2ο όρισμα ένα "StringSplitOptions", για το αν θα κρατάει ή όχι blank tokens.

 

Και υποθέτω και αρκετά ακόμα προβλήματα τα οποία δεν ανακαλύψαμε γιατί κανείς δεν κάθησε να το αναλύσει. Τον κώδικα τον πήρα ξεκινώντας απ' αυτό που έδωσες και συνέχισα απο κει, και μάλιστα ανέφερα πως τα προβλήματα που εντοπίζω είναι "για παράδειγμα".

 

Αν πάντως είχες Intellisense το overload με StringSplitOptions δε θα χρειαζόταν να το ανακαλύψεις.

 

Διορθώνεται με casting: .Split( (char[])null, StringSplitOptions.RemoveEmptyEntries );

 

είναι όμως safe?

 

Το πρόβλημα είναι πως το null είναι αποδεκτή τιμή για οποιοδήποτε reference type, επομένως το null δεν "είναι" τύπου string περισσότερο απ' οτι είναι τύπου Dictionary<Foo, Bar> ή τύπου WhateverCustomClass. O compiler σου λέει πως δεν μπορεί να καταλάβει ποιό από τα 2 overloads θέλεις να καλέσεις. Κάνοντας cast το null του δίνεις να καταλάβει και το θέμα τελειώνει εκεί. Με ποιό τρόπο θα μπορούσε να μην είναι safe?

 

Τώρα το αν η method που θα καλέσεις τελικά μόλις δει null αποφασίσει να σου κάνει format το δίσκο δεν είναι πρόβλημα του compiler.

 

Εννοείς πως με τα regex δεν χρειάζεται να δηλώσεις explicitly ποιοι χαρακτήρες θα λογιστούν ως token separators?

 

Δηλώνω explicitly: o separator είναι οποιοδήποτε word boundary (http://www.regular-expressions.info/wordboundaries.html).

 

 

Μιας που μιλάμε για regular expressions... είναι "kind of important" όταν γράφεις software.

 

 

 

ΔΕΝ ΥΠΑΡΧΕΙ ΚΑΝΕΝΑΣ ΣΤΟ ΠΡΟΣΩΠΙΚΟ ΤΟΥ INSOMNIA ΠΟΥ ΝΑ ΕΝΔΙΑΦΕΡΕΤΑΙ ΚΑΙ ΝΑ ΜΠΟΡΕΙ ΝΑ ΚΑΝΕΙ ΚΑΤΙ ΓΙΑ ΤΟ ΓΕΓΟΝΟΣ ΟΤΙ Ο EDITOR ΕΙΝΑΙ ΤΟΣΟ ΑΘΛΙΟΣ;;;

 

 

Εγώ πάλι ρε παιδιά δεν καταλαβαίνω γιατί δεν μπορείτε να αποδεχτείτε πως ο κάθε άνθρωπος έχει διαφορετικούς κώδικες και μεθοδολογίες.

 

Αυτό μπορούμε να το αποδεχτούμε. Εκείνο που μας δυσκολεύει είναι το να δείχνεις σε κάποιον το copy/paste κι αυτός να σου λέει ότι μια χαρά την κάνει τη δουλειά πληκτρολογώντας το ίδιο κείμενο manually πολλές φορές.

 

Η μεθοδολογία που επιλέγεις είναι αντικειμενικά αντιπαραγωγική και (συζητίσιμο, αλλά κατά την άποψή μου επίσης αντικειμενικό) δεν έχει να προσφέρει τίποτα πέραν του ότι το N++ είναι ένα γνώριμο εργαλείο ενώ με το VS βγαίνεις εκτός comfort zone. Αν απλά το θέμα ήταν να δεις τι γίνεται under the hood όταν πατάς compile, το VS έχει ειδικό output window όπου με τις κατάλληλες ρυθμίσεις φαίνεται ακριβώς το τι συμβαίνει. Σε προηγούμενο post είχα δώσει και link για όλα τα options του compiler (csc). Για τους λόγους αυτούς λοιπόν, αντικειμενικό και το ότι το N++ δεν έχει να προσφέρει τίποτα.

 

Σταματάω εδώ για να μην διαψέυσω τον εαυτό μου σχετικά με το ότι μπορούμε να το αποδεχτούμε. :P

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...

FYI ο κώδικας που παραθέτεις στην κλίμακα 1-10 παίρνει μετα βίας το 3 -- έχει μια ολόκληρη σειρά από χοντρά προβλήματα σχεδιασμού. Τελείως ενδεικτικά αναφέρω:

  1. Γενικά είναι κώδικας C γραμμένος με σύνταξη C#
  2. Έχει κατουρήσει στον τάφο της έννοιας του separation of concerns -- η ίδια method κάνει αποδοχή εισόδου, validation και επιστροφή τελικού αποτελέσματος
  3. To validation γίνεται με πολύ άσχημο τρόπο (ειδικά η επιλογή του error message...)
  4. Κάνει modify το this (γιατί? με ποιά λογική να μην είναι static και να επιστρέφει ένα καινούριο instance?) αλλά... το επιστρέφει κιόλας (εκτός συγκεκριμένων περιπτώσεων αυτό είναι τεράστιο red flag)

 

Δεκτές οι παρατηρήσεις, αν και θα προτιμούσα να συνοδεύονταν με κώδικα που θα έκανε demonstrate την καλή πρακτική (btw, την συνάρτηση την έκανα συνειδητά να κάνει πολλές δουλειές, θα αυτονομήσω τμήματά της όταν προσθέσω διαχείριση command-line argumets).

 

Το πρόβλημα είναι πως το null είναι αποδεκτή τιμή για οποιοδήποτε reference type, επομένως το null δεν "είναι" τύπου string περισσότερο απ' οτι είναι τύπου Dictionary<Foo, Bar> ή τύπου WhateverCustomClass. O compiler σου λέει πως δεν μπορεί να καταλάβει ποιό από τα 2 overloads θέλεις να καλέσεις. Κάνοντας cast το null του δίνεις να καταλάβει και το θέμα τελειώνει εκεί. Με ποιό τρόπο θα μπορούσε να μην είναι safe?

 

Οπότε αποτελεί ή όχι πρόβλημα (στην αρχή το χαρακτηρίζεις ως "πρόβλημα" αλλά στο τέλος ως "safe"); Αν αποτελεί πρόβλημα, ποιος κώδικας θεωρείται good practice σε αυτή την περίπτωση;

 

Δηλώνω explicitly: o separator είναι οποιοδήποτε word boundary (http://www.regular-exp<b></b>ressions.info/wordboundaries.html).

 

 

Μιας που μιλάμε για regular exp<b></b>ressions... είναι "kind of important" όταν γράφεις software.

 

 

Προσωπικά μου έχουν χρειαστεί ελάχιστες φορές.

 

Αυτό μπορούμε να το αποδεχτούμε. Εκείνο που μας δυσκολεύει είναι το να δείχνεις σε κάποιον το copy/paste κι αυτός να σου λέει ότι μια χαρά την κάνει τη δουλειά πληκτρολογώντας το ίδιο κείμενο manually πολλές φορές.

 

Η μεθοδολογία που επιλέγεις είναι αντικειμενικά αντιπαραγωγική και (συζητίσιμο, αλλά κατά την άποψή μου επίσης αντικειμενικό) δεν έχει να προσφέρει τίποτα πέραν του ότι το N++ είναι ένα γνώριμο εργαλείο ενώ με το VS βγαίνεις εκτός comfort zone.

 

Δεν βρίσκομαι σε στάδιο παραγωγικότητας αλλά εκμάθησης. Προτιμώ να δυσκολευτώ στην αρχή αλλά να πάρω βάσεις που θα μου εντυπωθούν, παρά να χαίρομαι με το IDE μου κρύβει τα mechanics για να μου δημιουργήσει αίσθηση "παραγωγικότητας" αλλά όταν χρειαστεί να αλλάξω περιβάλλον να χάσω τα αυγά και τα πασχάλια.

 

Αν απλά το θέμα ήταν να δεις τι γίνεται under the hood όταν πατάς compile, το VS έχει ειδικό output window όπου με τις κατάλληλες ρυθμίσεις φαίνεται ακριβώς το τι συμβαίνει. Σε προηγούμενο post είχα δώσει και link για όλα τα options του compiler (csc). Για τους λόγους αυτούς λοιπόν, αντικειμενικό και το ότι το N++ δεν έχει να προσφέρει τίποτα.

 

Σταματάω εδώ για να μην διαψέυσω τον εαυτό μου σχετικά με το ότι μπορούμε να το αποδεχτούμε. :P

 

Tο "csc /?" μια χαρά με εξυπηρετεί προς το παρόν. Ομοίως και το Notepad++.

 

Παρεμπιπτόντως, για να τελειώνουμε με αυτή την ιστορία (αυτό πάει και στον "μη ξεροκέφαλο" παπι)), να σας δώσω κι ένα παραπάνω κίνητρο για να μπορέσετε να το αποδεχτείτε όσο το δυνατόν πιο ανώδυνα... ο Herbert Schildt όχι μόνο δείχνει να μην έχει πρόβλημα με την προσέγγισή μου, αλλά την ενθαρρύνει κιόλας...

 

C#4.0 - The Complete Reference - Page #14

 

Using csc.exe, the C# Command-Line Compiler

 

Although the Visual Studio IDE is what you will probably be using for your commercial

projects, some readers will find the C# command-line compiler more convenient, especially

for compiling and running the sample programs shown in this book. The reason is that you

don’t have to create a project for the program. You can simply create the program and

then compile it and run it—all from the command line. Therefore, if you know how to use

the Command Prompt window and its command-line interface, using the command-line

compiler will be faster and easier than using the IDE.

 

Οπότε να προσθέσω κι εγώ (επειδή μου τα έχετε κάνει τσουρέκια με αυτό το θέμα): if you don't know how to use the Command Prompt window and its command-line interface, it's never too late :P

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεκτές οι παρατηρήσεις, αν και θα προτιμούσα να συνοδεύονταν με κώδικα που θα έκανε demonstrate την καλή πρακτική

 

Και γω αυτό σκέφτηκα να κάνω αρχικά, αλλά μετά συνειδητοποίησα ότι λείπουν κάποια κομμάτια του παζλ οπότε άλλαξα γνώμη. Τέλος πάντων, ας πούμε κάπως έτσι:

 

>class GreekName {
   public string Text { get; set; }

   public bool Validate()
   {
       return this.GetValidationerror() == null;
   }

   public string GetValidationerror()
   {
       if (string.IsNullOrEmpty(this.Text))
       {
           return "The name cannot be blank.";
       }

       if (this.Text.Length < 2)
       {
           return "Name too short.";
       }

       if (!this.Text.All(c => char.IsLetter(c) || char.IsWhiteSpace(c)))
       {
           return "Only letters allowed.";
       }

       return null;
   }
}

 

 

και μετά κάπου εκτός της class:

 

>private static GreekName ReadNameFromConsole(string prompt, bool verbose)
{
   var greekName = new GreekName();

   while (!greekName.Validate())
   {
       if (greekName.Text != null && verbose)
       {
           Console.WriteLine(greekName.GetValidationerror());
       }
       if (prompt != null)
       {
           Console.Write(prompt);
       }
       greekName.Text = (Console.ReadLine() ?? string.Empty).Trim();
   }

   return greekName;
}

 

 

(btw, την συνάρτηση την έκανα συνειδητά να κάνει πολλές δουλειές, θα αυτονομήσω τμήματά της όταν προσθέσω διαχείριση command-line argumets).

 

Γιατί όμως να κάνεις κάτι που ξέρεις ότι είναι 100% λάθος αν μπορείς να κάνεις κάτι που είναι λιγότερο λάθος; (ακόμα κι αν δεν έχεις ακόμα αρκετά δεδομένα για να αποφασίσεις τι είναι "σωστό")

 

Οπότε αποτελεί ή όχι πρόβλημα (στην αρχή το χαρακτηρίζεις ως "πρόβλημα" αλλά στο τέλος ως "safe"); Αν αποτελεί πρόβλημα, ποιος κώδικας θεωρείται good practice σε αυτή την περίπτωση;

 

Πρόβλημα = compiler error. Κάνεις cast και problem solved. Δεν έχει κάτι περισσότερο το συγκεκριμένο θέμα.

 

Προσωπικά μου έχουν χρειαστεί ελάχιστες φορές.

 

Εμένα πάλι δε μου έχει χρειαστεί ιδιαίτερα η fgets. Βάζω fgetc μέσα σ' ένα loop και καθάρισα. ;)

 

Τέλος όσον αφορά τα περι N++, command line και Schildt: εγώ πάλι έχω ένα project στο VS που όποτε θέλω να γράψω κάτι non-trivial μεν αλλά για πέταμα δε, απλά σβήνω όλα τα περιεχόμενα του Whatever.cs (CTRL+A, DEL), γράφω ο,τι είναι να γράψω, CTRL+TAB γράφω στο Program.cs στη Main ο,τι χρειάζεται, CTRL+F5 και τέλος. Καθ' όλη τη διάρκεια απολαμβάνω IntelliSense και R#. Δεν είμαι σίγουρος με ποιό τρόπο είναι faster το να τα κάνεις από command line αλλά ας μη το συζητήσουμε περισσότερο.

 

Τώρα το να λες ότι επειδή κάποιος χρησιμοποιεί VS δεν ξέρει να κάνει τα ίδια κι απο command line είναι σα να λες ότι επειδή πάει στη δουλειά με το αμάξι δεν ξέρει να κάνει ποδήλατο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

 

 

Και γω αυτό σκέφτηκα να κάνω αρχικά, αλλά μετά συνειδητοποίησα ότι λείπουν κάποια κομμάτια του παζλ οπότε άλλαξα γνώμη. Τέλος πάντων, ας πούμε κάπως έτσι:

 

 

 

>class GreekName {
   public string Text { get; set; }

   public bool Validate()
   {
       return this.GetValidationerror() == null;
   }

   public string GetValidationerror()
   {
       if (string.IsNullOrEmpty(this.Text))
       {
           return "The name cannot be blank.";
       }

       if (this.Text.Length < 2)
       {
           return "Name too short.";
       }

       if (!this.Text.All(c => char.IsLetter(c) || char.IsWhiteSpace(c)))
       {
           return "Only letters allowed.";
       }

       return null;
   }
}

 

 

και μετά κάπου εκτός της class:

 

>private static GreekName ReadNameFromConsole(string prompt, bool verbose)
{
   var greekName = new GreekName();

   while (!greekName.Validate())
   {
       if (greekName.Text != null && verbose)
       {
           Console.WriteLine(greekName.GetValidationerror());
       }
       if (prompt != null)
       {
           Console.Write(prompt);
       }
       greekName.Text = (Console.ReadLine() ?? string.Empty).Trim();
   }

   return greekName;
}

 

 

 

Thanks για τον κώδικα. Έχω κι εγώ σκοπό να αυτονομήσω το validation, όταν θα κάνω το πρόγραμμα να δέχεται το input και ως command-line-arguments, οπότε θα χρειαστούν κι άλλες τροποποιήσεις.

 

Btw, το σκεπτικό των error-messages σε πίνακα είναι για να μπουν κάποια στιγμή ως hash-table ή όποια άλλη δομή μου παρέχει η γλώσσα (όταν δω τι τρόπους μου παρέχει) και να τυπώνω με hashing σε όποιες ρουτίνες τα χρειαστώ. Έτσι αφενός αν θέλω να τροποποιήσω ένα message θα το κάνω edit σε ένα μέρος, κι αφετέρου θα μπορώ να έχω πολύγλωσσα version.

 

Προφανώς η επιλογή αυτή της υλοποίησης είναι αποτέλεσμα του C background μου καθώς και της μη επαρκούς ακόμα γνώσης της C#

 

Γιατί όμως να κάνεις κάτι που ξέρεις ότι είναι 100% λάθος αν μπορείς να κάνεις κάτι που είναι λιγότερο λάθος; (ακόμα κι αν δεν έχεις ακόμα αρκετά δεδομένα για να αποφασίσεις τι είναι "σωστό")

 

Επειδή γράφω κώδικα μαθαίνοντας την γλώσσα, οπότε δεν είμαι σε θέση να γνωρίζω εκ των προτέρων αν, ποιες και πόσες αλλαγές θα χρειαστεί να ξανακάνω. Οπότε τα γράφω όπως μου έρχεται για να δω αν κάνουν τη δουλειά που θέλω εκείνη την ώρα, με όσο "prediction" μου επιτρέπουν οι λιγοστές μου ακόμα γνώσεις στην C#.

 

Εμένα πάλι δε μου έχει χρειαστεί ιδιαίτερα η fgets. Βάζω fgetc μέσα σ' ένα loop και καθάρισα. ;)

 

Δεν το έπιασα για να είμαι ειλικρινής.

 

Τέλος όσον αφορά τα περι N++, command line και Schildt: εγώ πάλι έχω ένα project στο VS που όποτε θέλω να γράψω κάτι non-trivial μεν αλλά για πέταμα δε, απλά σβήνω όλα τα περιεχόμενα του Whatever.cs (CTRL+A, DEL), γράφω ο,τι είναι να γράψω, CTRL+TAB γράφω στο Program.cs στη Main ο,τι χρειάζεται, CTRL+F5 και τέλος. Καθ' όλη τη διάρκεια απολαμβάνω IntelliSense και R#. Δεν είμαι σίγουρος με ποιό τρόπο είναι faster το να τα κάνεις από command line αλλά ας μη το συζητήσουμε περισσότερο.

 

Όταν θες να σώζεις το κάθε πρόγραμμα ξεχωριστά τι κάνεις; Υποθέτεις πως γράφω κώδικα τον τρέχω και τον σβήνω για να γράψω τον επόμενο; Αν ναι, δεν υποθέτεις σωστά

 

Άλλο παράδειγμα, με το Notepad++ έχω ανοιχτά 2 .cs αρχεία: MyExtras.cs και Test.c με το 1ο βγάζει dll και το άλλο βγάζει .exe χρησιμοποιώντας κλάσεις του dll.

 

Μόλις θέλω να προσθαφαιρέσω μια κλάση στο MyExtras.cs την γράφω, πατάω F6->CS DLL και μου ανανεώνει το .dll. Στο καπάκι την καλώ στον κώδικα του Test.cs, πατάω F6->CS EXE και μου παράγει και μου τρέχει το Test.exe χρησιμοποιώντας την ανανεωμένη .dll

 

Στο VS (ή σε όποιο άλλο IDE) δεν ξέρω πως γίνεται κάτι τέτοιο, και όπως έγραψα και πριν στην παρούσα φάση δεν με ενδιαφέρει να μάθω κάποιο συγκεκριμένο IDE αλλά τα basic mechanics της γλώσσας.

 

Τώρα το να λες ότι επειδή κάποιος χρησιμοποιεί VS δεν ξέρει να κάνει τα ίδια κι απο command line είναι σα να λες ότι επειδή πάει στη δουλειά με το αμάξι δεν ξέρει να κάνει ποδήλατο.

 

Δεν είπα πως "δεν ξέρετε", είπα "αν δεν ξέρετε".

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 3 χρόνια αργότερα...

Γεια σας, ασχολούμαι με την C# και έχω κάποιες ερωτήσεις - απορίες. Μαθαίνω τη γλώσσα από εδώ: http://www.tutorialspoint.com/csharp/  είναι καλή σελίδα ? Ποια προτείνετε εσείς ?

 

Έχω προχωρήσει πολύ μακριά αλλά εδώ --> C# - Encapsulation έχω μια απορία, την ενθυλάκωση γιατί πρέπει να την χρησιμοποιούμε ?

 

Δηλ τι να κρύψω - προστατεύσω ?

 

Ευχαριστώ εκ των προτέρων

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τα access specifiers χρησιμοποιούνται για να ορίσουν την "ορατότητα" των μεταβλητών έξω από την κλάσση. Αυτό στην αρχή φαίνεται να μην έχει νόημα αλλά είναι πολύ χρήσιμο όταν συνεργάζεσαι με άλλους αλλά και να αποτρέψει τον εαυτό σου να "κόψει δρόμο" σε κάτι γιατί είναι πιο εύκολο!.

 

ΠΧ: Συνήθως λέμε ότι οι μεταβλητές πρέπει να είναι private και όποιος θέλει να έχει δικαίωμα πρόσβασης θα πρέπει να περάσει από get-set μεθόδους.

 

Σκέφτεσαι: "μία μεταβλητή που απλά την χρησιμοποιώ χωρίς τπτ άλλο γιατί να την βάλω σε συνάρτηση;". Αργότερα μπορεί να μην την χρησιμοποιείς πια απλά αλλά να θέλεις να κάνεις και κάποιον έλεγχο. Θα ψάχνεις όλα τα σημεία που χρησιμοποιείται για να τα αλλάξεις;

 

Έστω ότι έχεις συνάρτηση (γιατί κάνεις ελέγχους) αλλά την έχεις αφήσει public και την μεταβλητή. Κάποια στιγμή επειδή θέλεις να κάνεις κάτι και οι έλεγχοι σε δυσκολεύουν σκέφτεσαι "έλα μωρέ, θα πάρω κατευθείαν την μεταβλητή, αφού είναι public!". Και κάπου εκεί αρχίζει το μπάχαλο στον κώδικα και τα bug που δεν ξέρεις γιατί υπάρχουν αφού έχεις έλεγχο στη συνάρτηση!

 

 

Οπότε στην ουσία "κρύβεις" τις μεταβλητές που δεν θέλεις να μπορούν να δουν οι "άλλοι" έξω από την κλάσση αλλά και προστατεύεις τις μεταβλητές σου ώστε να μην μπορέσει κάποιος να τις τροποποιήσει πέρα από τον προκαθορισμένο τρόπο που ορίζεις όταν φτιάχνεις την κλάσση.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ενα κλασσικο παραδειγμα ειναι η κλαση Date. Δεν θα ηθελες η ωρα να παρει τρελες τιμες(>23), ετσι δεν ειναι;

Εσυ ως σχεδιαστης μπορει να μην την χρησιμοποιησεις με λαθος τροπο αλλα σε ενα μεγαλο project ειναι πολυ πιθανο. Πραγμα το οποιο αποτρεπεται με τις καταλληλες setter μεθοδους. Οπως επισης μπορει να το κανει ο partner σου αν δεν εχεις δηλωσει καταλληλα pre/post - conditions.

 

Συνηθως τις ορατες μεταβλητες τις δηλωνουμε ως static final μιας και ειναι ανεξαρτητες κι ακινδυνες. Π.χ Math.pi.

 

Αλλος λογος ειναι η ασφαλεια. Ενας κακοβουλος χρηστης αν ξερει τι επικινδυνο κι ακαλυπτο στοιχειο περιεχει μια κλαση μπορει να το εκμεταλλευτει προς συμφερον του. Για αυτην την δουλεια ειναι ιδιαιτερα χρησιμα τα Reflections.

 

Επισης το encapsulation χρησιμοποιειται και για μεθοδους. Π.χ μια μεθοδος καλει μια βοηθητικη συναρτηση ενω η δευτερη -η καλουμενη- δεν προσφερει κατι στον προγραμματιστη.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Από ποιους να τα κρύψω? Από τους άλλους προγραμματιστές - χρήστες ? Ναι, αλλά τότε σαν τους περιορίζω να χρησιμοποιήσουν τις δικές μου μεταβλητές και μεθόδους, όπως και στις βιβλιοθήκες που φτιάχνουν οι προγραμματιστές.


Άρα τα χρησιμοποιούμε για περισσότερη ασφάλεια, από του άλλους.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τον ορισμό της ενθυλάκωσης το έχω καταλάβει, αλλά στον τρόπο λειτουργίας της μπερδεύομαι. Ας πούμε ότι έχω δύο κλάσεις και έχω βάλει private μεταβλητές και public μεθόδους και την main, τώρα ο άλλος προγραμματιστής πως θα διαβάσει αυτές κλάσεις, δηλ εγώ τη πρέπει να του δώσω, όλο τον κώδικά ή μόνο το όνομα του αντικειμένου που δημιούργησα ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...