Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Ciao a tutti.
Ricollegandomi a questo http://www.pierotofy.it/pages/extras/forum/16/1029500-[vbn ... Vorrei postare un po' di codice, così magari mi potete dare qualche suggerimento per ottimizzare il tutto.. Mi rendo conto che su questo forum ci sono discussioni di livello ben più elevato della mia ma magari a qualche utente alle prime armi possono interessare anche argomenti di base..
Sto realizzando un parser per delle stringhe codificate in un certo modo.
Avevo pensato di organizzarla così:
http://img8.imageshack.us/img8/4269/esempioschema.jpg Sull'evento KeyUp di una textbox rilevo il testo inserito:
Codice sorgente - presumibilmente VB.NET
If e.KeyCode= Keys.EnterThen'evento tasto INVIO
e.SuppressKeyPress=True
Dim R AsNew Stringa 'Istanzio una nuova STRINGA
R.AnalizzaStringa(textbox1.Text)'Richiamo il Metodo ANALIZZASTRINGA
La Classe stringa riceve il testo e tramite delle espressioni regolari che ho scritto separa la stringa nei suoi vari elementi
Codice sorgente - presumibilmente VB.NET
PublicClass Stringa
PublicSub AnalizzaStringa(ByValstrAsString)
Ifstr.Length= 0 ThenExitSub
Dim MatchCollect As MatchCollection
Dim t As Match
Dim strRegex AsString="ecc ecc"
Se l'espressione regolare restituisce match adeguato istanzio un nuovo oggetto Elemento1, che conterrà un singolo elemento della stringa inserita
Codice sorgente - presumibilmente C# / VB.NET
Dim Elem1 As New Elemento1(t.Groups("Elem1").Value)
Ho quindi creato la Classe Elemento1 dove ho messo dei metodi per verificare la correttezza dell'elemento1
Codice sorgente - presumibilmente VB.NET
PublicClass Elemento1
Inherits FormattaStr 'classe con funzione x formattare la stringa
Private Elem1Array AsNew List(Of String)(NewString(){"A", "AB", "B", "BS", "BT", "Abs"})'array contenente tutti i possibili valori di elem1
Dim _Elem AsString
Dim E AsNew ErrorWr
PublicSubNew(ByValstrAsString)
_Elem =str
_Elem = FormToUpperInv(_Elem)'1 carattere Maiuscolo e resto minuscolo
IfNot Elem1Array.Contains(_Elem)Then'se l'elemento è sbagliato
E.WriteError("Elemento1", _Elem)'-> classe per segnalare l'errore
EndIf
EndSub
PublicFunctionstr()AsString
Return _Elem
EndFunction
EndClass
Lo stesso discorso vale per gli altri elementi, anche se trattandosi di pezzetti di stringa più lunghi ci sono altre regole per valutare la correttezza di quanto inserito.
Le mie domande sono:
1) si può migliorare qualcosa, nelle dichiarazioni/creazioni delle classi ?
2) la classe ErrorWr espone un metodo che non fa altro che ricevere 2 "stringhe" contenenti l'errore per visualizzarlo con messagebox.show... Un eventuale comando "exit sub" per bloccare l'elaborazione dove va messo?
3) Se volessi definire degli errori "standard" tipo "elemento inesistente", "elemento doppio", "con elemento y non è possibile inserire elemento x", come mi consigliate di procedere?
Grazie a tutti per l'attenzione
Mi rendo conto che usare VB.NET per un programma del genere è come usare un cannone per ammazzare le mosche, ma se non altro sto imparando qualcosa di molto utile e interessante..
La classe Stringa può andare, ma potrebbe essere migliorata. La mia opinione è di non esporre un costruttore pubblico. Infatti tu puoi creare una nuova Stringa, come hai fatto nel codice di esempi, che può non contiene nulla. Perciò è sempre possibile creare un oggetto incoerente. Dovresti invece convertire AnalizzaStringa in un metodo factory:
http://totemslair.org/guide/viewchapter.php?guida=vb&id=25
La classe Elemento1 è molto... sgraziata. Per prima cosa, Elemento1 eredita da una classe base che non espone funzionalità relative all'elemento ma alle stringhe e, pur essendo Elemento1 stesso una qualche forma derivata di stringa, non ha nulla a che vedere con le stringhe in generale. Dovresti spostare tutti i metodi di FormattaStr o in un modulo accessibile da tutti (proprio come Math espone funzioni di calcolo) oppure, ancora meglio, convertire tutti questi metodi in metodi di estensione per la classe String:
http://totemslair.org/appunti/viewtutorial.php?id=8 Ora, tolto il grado di derivazione da FormattaStr, puoi concentrarti sull'elemento. Pare strano... molto strano, che esistano più classi chiamate Elemento1, Elemento2, ecc... Se questo è necessario io non lo so, poiché dipende da come devi parsare la stringa. Tuttavia sono abbastanza sicuro che dovresti accomunare queste classi facendole derivare tutte dalla stessa classe base (magari astratta) Elemento.
http://totemslair.org/guide/viewchapter.php?guida=vb&id=36
Infine, gli errori non dovrebbero essere semplicemente trascritti da qualche parte. Dovresti invece lanciare delle eccezioni con Throw. In questo modo è molto più semplice definire i tipi di errore: basta creare delle classi che ereditino da Exception e poi usare Throw per lanciarne delle istanze. Ad esempio:
Codice sorgente - presumibilmente VB.NET
Class InvalidElementException
Inherits Exception
PublicSubNew(ByVal message AsString)
MyBase.Message= message
EndSub
EndClass
'...
IfNot Elem1Array.Contains(_Elem)Then'se l'elemento è sbagliato
Ciao Totem, grazie mille per la risposta e per i tuoi preziosi consigli.
1) questione: Metodo Factory
Ho pensato di creare un metodo Factory sia per creare (e verificare) la stringa sia nel momento in cui creo i singoli elementi.
Ho fatto quindi
'inserisco tutti gli elementi e faccio le verifiche adeguate
ReturnNew Stringa(Elem1, Elem2.... )
endfunction
........
PrivateSubNew(ByRef Elem1 As Elemento1, ByVal Elem2 As Elemento2)
_Elem1 = Elem2 '
_Elem2 = Elem2
EndSub
endClass
Come vedi ho usato le Extension per crearmi quei metodi aggiuntivi alla classe string che mi servivano per formattare la stringa come volevo io.. (davvero interessanti!)
Rispetto alle classi astratte, ho letto l'interessante esempio che mi hai linkato ma preferisco lasciare l'organizzazione così. Anche perché qua scrivo "Elem1" ecc ma nel mio programma gli elementi hanno nomi diversi e contengono dati diversi (sempre caratteri alfanumerici) ma sono ben distinti.
Concettualmente mi sembra di aver capito abbastanza come funziona il tutto.
L'unica cosa è che mi sembra di dover scrivere tanto codice, perchè gli elementi di stringa sono 7.. Non è che così facendo si occupa molta memoria, a dover dichiarare le variabili tante volte? Se la stringa (o il singolo elemento) non sono corretti, ha senso scrivere "return nothing" e comunque avendo l'exception esco dalla function "Create" ed evidenzio all'utente l'errore?
Per quanto riguarda la gestione degli errori, finisco con la Classe string e poi mi ci metto. Al limite se ho dubbi scrivo ancora..
Di nuovo Grazie mille!
Ultima modifica effettuata da Renny il 10/08/2011 alle 15:29
"Tanta" memoria dipende dal contesto. E' difficile occupare tanta memoria usando solo stringhe, a meno che, ovviamente, non lasci in giro dei memory leak assurdi.
Appunto perché ti sembra di dover scrivere cose ripetute è opportuno avere una classe base Elemento, che esponga le funzionalità comuni a tutti gli elementi.
Per quanto riguarda Return Nothing, sebbene sia una pratica abbastanza comune restituire oggetti nulli, non si tratta della soluzione migliore. Usa invece un'eccezione, esattamente come hai fatto per str.IsNullOrEmpty.
Altri appunti:
- Dopo Throw, il flusso di esecuzione viene deviato al di fuori del metodo e, se esiste un blocco Catch opportuno, all'interno di quest'ultimo. Perciò, in questo codice, l'else è inutile:
Codice sorgente - presumibilmente VB.NET
IfString.IsNullOrEmpty(str)Then
ThrowNew QualcheEccezione()
Else
'...
EndIf
- Cerca di usare eccezioni standard dove possibile. Ad esempio, nel caso di stringa vuota, potresti lanciare un'eccezione di tipo ArgumentException, che indica che un argomento del metodo non è valido. In questo caso è l'unica stringa passata a non essere valida, dato che è vuota.
- Usa metodi di estensione con dei nomi comprensibili. E non ripeterti. Ad esempio, LastS è inutile, dato che esiste il metodo String.EndsWith(str), il quale restituisce vero se la stringa su cui è richiamato termina con str. str.LastS è simile a str.EndsWith("S").
LocArray da dove viene? Non è molto elegante usare una variabile globale nel corpo di una classe.
Ciao Totem, ciao ragazzi...
Sto ancora lavorando per creare le mie classi usando metodi Factory, per verificare i dati e solo se è tutto ok, posso instanziare l'oggetto.
Il mio dubbio è questo:
Codice sorgente - presumibilmente VB.NET
SharedFunction Create(ByValstrAsString)As Elem1
Dim ElemArray AsNew List(Of String)(NewString(){"elementi vari"
Dim ElemList AsNew List(Of String)(str.Split("."))'divido la stringa
Dim DetsStr AsString=Nothing
str= formatta(str)'->> richiamo una funzione all'interno della classe Elem1
returnnew Elem1(str)
endFunction
PrivateFunction formatta(strasstring)asstring
str=str.toLower' solo per fare l'esempio
returnstr
endFunction
Il mio dubbio è il seguente: non posso richiamare la funzione "formatta" all'interno del metodo factory perché è definito shared. L'errore che mi riporta Visual Studio è appunto "Impossibile fare riferimento a un membro di istanza di una classe all'interno di un metodo condiviso o di un inizializzatore di membri condivisi senza un'istanza esplicita della classe."
Come posso fare per richiamare la mia funzione all'interno del metodo Create?
Devo per forza metterla in una classe astratta e poi far ereditare tale classe base alla classe Elem1, dove c'è il create? (Ho provato un po,senza successo).. Questa cosa non è che mi piaccia tanto, perché la funzione che sto cercando di usare mi serve solo all'interno di elem1.. La cosa più semplice è spostare il codice nel metodo create, ma mi pare impossibile che non ci siano altre soluzioni. Che dite?
Ci mancherebbe altro che VS ti dia errore. E' impossibile fare riferimento a qualunque membro d'istanza da un metdo statico. Il motivo è talmente ovvio che non mi dilungo neanche a spiegarlo. A ogni modo, non ti basta rendere la funzione Formatta anche essa statica? Non vedo dove sia il problema.
Spero di aver capito bene ciò che intendi fare.
Ultima modifica effettuata da Phil93 il 12/08/2011 alle 3:10
Appunto, è un tuo errore. Formatta dovrebbe essere un metodo di estensione di String. Non ha senso dichiararlo come metodo d'istanza, poiché non fa uso di nessun campo d'istanza. Al più potrebbe essere statico, come suggeriva Phil93.
Ciao ragazzi, grazie per la risposta.
In realtà la mia intenzione con il codice che avevo scritto era molto banale (e forse anche un po' stupida). Semplicemente volevo che il codice della funzione "formatta" fosse a parte, ma solo per tirarlo fuori e metterlo come funzione poco più un là, nella classe che lo utilizza. tipo
In questo modo la funzione Formatta serve solo a evitare di appesantire il codice "di controllo" che genera l'elemento. Ma in effetti è una funzione con qualche if, che posso utilizzare solo in questa classe perché troppo specifica. Non ha senso come extention, (forse neanche tanto come "funzione), ma alla fine l'ho dichiarata così:
Ne è uscito quasi un'ossimoro: una funzione condivisa ma privata, solo per la classe... Così fa il suo lavoro, anche se è sicuramente un modo stupido di procedere.. che dite?
Resta il fatto che con il vostro aiuto sono andato a rileggermi con attenzione questa OTTIMA guida:
http://totemslair.org/guide/viewchapter.php?guida=vb&id=23 Di nuovo grazie