PDA

View Full Version : [C#] Primo approccio abbastanza deludente...


whit3noise
02-03-2015, 22:41
Ciao a tutti, scrivo qui per avere il vostro parere (e anche per sfogarmi un po'...). [PS: scusate se il post è troppo lungo]

Sono passato da circa 2 giorni a C# e globalmente devo dire che è un buon linguaggio... ma ci sono alcune cose che non riesco proprio a digerire.

Scrivo solo quelle che ho trovato finora, ma sicuramente ce ne saranno altre...

1) Interfacce
Non è possibile inserire variabili nelle interfacce... Ma per quale cavolo di motivo ???
Se ho delle classi che implementano tutte la stessa interfaccia e che usano tutte una stessa variabile,
devo definire n volte la variabile in tutte le classi ???
Ok, è risolvibile facendo estendere alle classi una classe abstract invece di implementare una interfaccia...
...ma allora dico io... le potevano eliminare proprio queste interfacce... No?

PS:
la cosa assurda è che invece le proprietà (che sono "più evolute") si possono inserire... Mah...

2) Scope delle variabili locali.
Che fine hanno fanno le regole di scoping che gli umani conoscevano fino ad adesso (perlomeno nei linguaggi C-like) ??? :eek:
Questa è davvero fastidiosa. :mad:

Questo codice non compila:

for (int i = 0; i < 10; i ++)
Console.WriteLine ("i = " + i);

int i = 911;
Console.WriteLine ("i = " + i);


Stessa cosa per questo:

{
int i = 113;
Console.WriteLine ("i = " + i);
}

int i = 118;
Console.WriteLine ("i = " + i);


Error: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else.

...Ho pensato: forse allora funziona come Javascript... :confused:
Nel primo esempio, pensavo che la i dentro il for fosse visible 'fuori' il for...

for (int i = 0; i < 10; i ++)
Console.WriteLine ("i = " + i);

// int i = 911;
Console.WriteLine ("i = " + i);


...e invece:
The name 'i' does not exist in the current context.

Senza parole: Non è possibile più usare lo stesso nome di variabile anche se si trova in blocchi diversi... :Puke:

3) Trattamento orribile delle operazioni con i tipi primitivi

Premessa:
Principalmente uso java, ma il motivo principale per cui ho voluto provare C# è il supporto dei tipi unsigned che in java mancano...
Tralascio ovviamente la 'porcheria' che hanno fatto in Java 8 creando delle classi per 'fare operazioni' su variabili invece che tipi primitivi per sopperire a tale mancanza...

Per risolvere il problema in java il metodo migliore è semplicemente dichiarare tutte le variabili int, ed usare l'operatore & con la maschera appropriata.

Esempi:
se mi serve una variabile 'unsigned byte' (8 bit) la dichiaro int e uso ad es: x = (x + 10) & 0xFF;
se mi serve una variabile 'unsigned short' (16 bit) la dichiaro int e uso ad es: x = (x + 10) & 0xFFFF;
... ecc.

Bene...
Pensavo che passando a C# il problema dei tipi unsigned fosse una volta per tutte risolto, fino a quando non scopro come tratta le operazioni...

Davo per scontato che C# gestisse automaticamente l'overflow e l'underflow del valore delle variabili... povero illuso... :(

Come al solito questo esempio non compila:

byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2;


Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)
Coosa ??? :what: Ti sto dicendo io che sono tutti byte e cerchi di convertire i valori ad int ????

Conclusione:
Problema della 'sporcizia' del codice non risolto (quindi come java)... perchè praticamente bisogna riempire tutto il codice di cast...
o comunque usare la 'stessa tecnica' dell'"and" di java... :Puke: :incazzed:

Per compilare si deve eseguire obbligatoriamente un cast...

byte b3 = (byte) (b1 + b2)


Ho fatto l'esempio con i tipi unsigned ma lo stesso vale anche per i tipi signed.

4) Uso obblicatorio di chiamate a DLL per alcuni task in un linguaggio 'moderno' di alto livello ???
Penso che sicuramente ci saranno molti altri casi, io descrivo un semplice problema che mi è capitato...

Volevo semplicemente leggere gli eventi keyDown e keyUp in un form (in pratica mi interessava ottenere il KeyCode dei tasti).
Tutto bene fino a quando non mi accorgo che tramite API/metodi/campi 'normali' di C# non c'è modo di distinguere per i tasti modificatori (Shift, Ctrl e Alt) se
il tasto si trova a sinistra o destra.

Apparentemente (cercando anche in 'giro') l'unico modo è di usare System.Runtime.InteropServices.DllImport importando la dll user32.dll e usando la chiamata
GetAsyncKeyState... ...bruttissimo... :grrr:

5) Dichiarazione array
Ok, questo non è un vero problema, ma è veramente una cosa antipatica e soprattutto una perdita di tempo assurda.

Vorrei capire perchè è stato scelto di dichiarare un array con le parentesi quadre da inserire obbligatoriamente prima del nome dell'array e non continuare ad
usare la sintassi opposta (come tutti i linguaggi C-Like), o comunque se era 'proprio necessario', supportarle entrambe. :bsod:

Vi dico questo perchè mi sono accorto che, quando devo convertire dei pezzi di codice (scritti ad. es. in C/C++/Java) in C# perdo più tempo ad invertire l'ordine
delle parentesi quadre rispetto a sistemare il resto degli errori. :muro:

Un'altra cosa incompresibile è perchè non si può dichiarare un array bidimensionale come:
int [][] array = new int [10][20];

...ma invece si deve per forza usare:
int [,] array = new int [10, 20]; :nono:

6) Delegate e Interfacce
Devo ancora approfondire meglio l'argomento... quindi premetto che può essere una mia mancanza,
ma non riesco davvero a capire perchè devo usare i delegate quando posso fare benissimo la stessa cosa con le interfacce... :boh:
Qualcuno può spiegarmelo?


Per ora mi fermo qui... Ripeto queste sono cose (secondo me assurde) che ho trovato in appena due giorni di utilizzo di C#;
se ne trovo altre le scriverò...

Aspetto vostri commenti.

[Kendall]
03-03-2015, 09:30
Ciao a tutti, scrivo qui per avere il vostro parere (e anche per sfogarmi un po'...). [PS: scusate se il post è troppo lungo]

Sono passato da circa 2 giorni a C# e globalmente devo dire che è un buon linguaggio... ma ci sono alcune cose che non riesco proprio a digerire.

Scrivo solo quelle che ho trovato finora, ma sicuramente ce ne saranno altre...


Premessa: approcciarsi ad un nuovo linguaggio e pensare che sintassi, costrutti e compilatore debbano comportarsi in una maniera solo perchè suddetta sintassi assomiglia a quella di altri linguaggi è sostanzialmente sbagliato.
Se ti approcci al C# devi metterti nell'ordine delle idee di pensare come un programmatore C#, senza stare ogni 2x3 a fare paragoni con il Java (che poi, a mio modo di vedere, sarebbe un paragone poco lusinghiero per quest'ultimo).



1) Interfacce
Non è possibile inserire variabili nelle interfacce... Ma per quale cavolo di motivo ???
Se ho delle classi che implementano tutte la stessa interfaccia e che usano tutte una stessa variabile,
devo definire n volte la variabile in tutte le classi ???
Ok, è risolvibile facendo estendere alle classi una classe abstract invece di implementare una interfaccia...
...ma allora dico io... le potevano eliminare proprio queste interfacce... No?

PS:
la cosa assurda è che invece le proprietà (che sono "più evolute") si possono inserire... Mah...

Le interfacce sono dei "contratti": io classe Pippo sottoscrivo questa interfaccia e mi impegno a fornire un'implementazione per tal metodo e/o tale proprietà.
Detto questo, le variabili d'istanza sono dettagli d'implementazione della classe, pertanto non hanno senso all'interno di una interfaccia, in quanto le interfacce NON forniscono implementazione alcuna.
Se tutta una serie di classi condividono certi metodi e certe varibili, evidentemente l'interfaccia non è una soluzione adeguata.
Riguardo alle proprietà, queste non sono delle ivar più evolute. Concettualmente sono cose totalmente diverse che puoi piuttosto associare alla sfilza di getter e setter del Java.



2) Scope delle variabili locali.
Che fine hanno fanno le regole di scoping che gli umani conoscevano fino ad adesso (perlomeno nei linguaggi C-like) ??? :eek:
Questa è davvero fastidiosa. :mad:

...cut...

Senza parole: Non è possibile più usare lo stesso nome di variabile anche se si trova in blocchi diversi... :Puke:

L'evitare di usare lo stesso nome per più variabili all'interno dello stesso metodo è prima di tutto una buona regola.
Il compilatore non permette i casi che hai indicato, anche se alcuni sarebbero formalmente leciti, per evitare a monte tutta una serie di problemi.

Questo invece è concesso:

for (int i = 0; i < 10; i++) {
Console.WriteLine("i = " + i);
}

for (int i = 0; i < 10; i++) {
Console.WriteLine("i = " + i);
}




3) Trattamento orribile delle operazioni con i tipi primitivi

Premessa:
Principalmente uso java, ma il motivo principale per cui ho voluto provare C# è il supporto dei tipi unsigned che in java mancano...

...cut...

Bene...
Pensavo che passando a C# il problema dei tipi unsigned fosse una volta per tutte risolto, fino a quando non scopro come tratta le operazioni...

Davo per scontato che C# gestisse automaticamente l'overflow e l'underflow del valore delle variabili... povero illuso... :(

Come al solito questo esempio non compila:

byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2;


Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)
Coosa ??? :what: Ti sto dicendo io che sono tutti byte e cerchi di convertire i valori ad int ????

Conclusione:
Problema della 'sporcizia' del codice non risolto (quindi come java)... perchè praticamente bisogna riempire tutto il codice di cast...
o comunque usare la 'stessa tecnica' dell'"and" di java... :Puke: :incazzed:

Per compilare si deve eseguire obbligatoriamente un cast...

byte b3 = (byte) (b1 + b2)


Ho fatto l'esempio con i tipi unsigned ma lo stesso vale anche per i tipi signed.

Nel C# l'aritmetica dei tipi byte, sbyte, short e ushort viene espletata convertendo le variabili a Int32 ed eseguendo l'operazione (dando pertanto un risultato di tipo Int32.
Nei tipi con dimensione maggiore o uguale ad Int32 questo invece non avviene. Quindi due uint puoi sommarli senza che questi vengano convertiti in alcun modo.
Per il discorso dell'overflow, il C# permette di eseguire operazioni checked ed unchecked (la seconda è quella di default).



4) Uso obblicatorio di chiamate a DLL per alcuni task in un linguaggio 'moderno' di alto livello ???
Penso che sicuramente ci saranno molti altri casi, io descrivo un semplice problema che mi è capitato...

Volevo semplicemente leggere gli eventi keyDown e keyUp in un form (in pratica mi interessava ottenere il KeyCode dei tasti).
Tutto bene fino a quando non mi accorgo che tramite API/metodi/campi 'normali' di C# non c'è modo di distinguere per i tasti modificatori (Shift, Ctrl e Alt) se
il tasto si trova a sinistra o destra.

Apparentemente (cercando anche in 'giro') l'unico modo è di usare System.Runtime.InteropServices.DllImport importando la dll user32.dll e usando la chiamata
GetAsyncKeyState... ...bruttissimo... :grrr:

https://msdn.microsoft.com/en-us/library/system.windows.input.keyboard.iskeydown(v=vs.110).aspx


5) Dichiarazione array
Ok, questo non è un vero problema, ma è veramente una cosa antipatica e soprattutto una perdita di tempo assurda.

Vorrei capire perchè è stato scelto di dichiarare un array con le parentesi quadre da inserire obbligatoriamente prima del nome dell'array e non continuare ad
usare la sintassi opposta (come tutti i linguaggi C-Like), o comunque se era 'proprio necessario', supportarle entrambe. :bsod:

Vi dico questo perchè mi sono accorto che, quando devo convertire dei pezzi di codice (scritti ad. es. in C/C++/Java) in C# perdo più tempo ad invertire l'ordine
delle parentesi quadre rispetto a sistemare il resto degli errori. :muro:

Non capisco quale sia il problema. Davvero.



Un'altra cosa incompresibile è perchè non si può dichiarare un array bidimensionale come:
int [][] array = new int [10][20];

...ma invece si deve per forza usare:
int [,] array = new int [10, 20]; :nono:

A parte che la seconda è una sintassi molto più naturale della prima per dichiarare un array multidimensionale (in quanto prende proprio la forma di una matrice matematica), rimane quanto segue.

Nel C# puoi dichiarare array multidimensionali


int[,] array1 = new int[4, 2];
int[, ,] array2 = new int[4, 2, 10];


oppure array irregolari (jagged)


int[][] jagged = new int[3][];
jagged[0] = new int[5];
jagged[1] = new int[4];
jagged[2] = new int[2];


questi sono a tutti gli effetti array di array.



6) Delegate e Interfacce
Devo ancora approfondire meglio l'argomento... quindi premetto che può essere una mia mancanza,
ma non riesco davvero a capire perchè devo usare i delegate quando posso fare benissimo la stessa cosa con le interfacce... :boh:
Qualcuno può spiegarmelo?

I delegate sono concettualmente una funzionalità completamente diversa dalle interfacce.
Possono essere usati per espletare funzionalità simili in certi contesti, ma ciò non toglie che stai confrontando pere con mele.


Per ora mi fermo qui... Ripeto queste sono cose (secondo me assurde) che ho trovato in appena due giorni di utilizzo di C#;
se ne trovo altre le scriverò...

Aspetto vostri commenti.
Le trovi assurde perchè parti dal preconcetto che il C# DEVE comportarsi come il Java.
Questo è un approccio sbagliato.

Io ti consiglio di prenderti un buon libro di C# e di continuare l'apprendimento senza preconcetti.
Il C# è un linguaggio estremamente potente, con una serie di funzionalità ed un framework gigantesco alle spalle (e con quella che è probabilmente la miglior IDE sul mercato).

WarDuck
03-03-2015, 12:01
...

1) Interfacce
Non è possibile inserire variabili nelle interfacce... Ma per quale cavolo di motivo ???
Se ho delle classi che implementano tutte la stessa interfaccia e che usano tutte una stessa variabile,
devo definire n volte la variabile in tutte le classi ???
Ok, è risolvibile facendo estendere alle classi una classe abstract invece di implementare una interfaccia...
...ma allora dico io... le potevano eliminare proprio queste interfacce... No?

PS:
la cosa assurda è che invece le proprietà (che sono "più evolute") si possono inserire... Mah...


Perché rientra perfettamente nella definizione di interfaccia, così come prevista nell'OOP.

Se ti serve una classe astratta usi una classe astratta.


5) Dichiarazione array
Ok, questo non è un vero problema, ma è veramente una cosa antipatica e soprattutto una perdita di tempo assurda.

Vorrei capire perchè è stato scelto di dichiarare un array con le parentesi quadre da inserire obbligatoriamente prima del nome dell'array e non continuare ad
usare la sintassi opposta (come tutti i linguaggi C-Like), o comunque se era 'proprio necessario', supportarle entrambe. :bsod:


Semplice: "array di T" è un tipo di dato.

Ti faccio notare che anche Java è un linguaggio C-Like e gli array si dichiarano nella stessa maniera (di C#).

Se vogliamo la scelta bizzarra (ma sicuramente motivata in qualche modo) è più che altro quella di C e C++ che usano le parentesi dopo il nome della variabile.

Comunque è una diatriba molto simile a quella che vede ad esempio l'uso dell'asterisco per indicare il puntatore attaccato al tipo o al nome della variabile.

Io preferisco la prima per dire, per lo stesso identico motivo: un puntatore è un tipo di dato.

Sul resto ti ha già risposto Kendall.

whit3noise
03-03-2015, 16:25
Premessa: approcciarsi ad un nuovo linguaggio e pensare che sintassi, costrutti e compilatore debbano comportarsi in una maniera solo perchè suddetta sintassi assomiglia a quella di altri linguaggi è sostanzialmente sbagliato.
Se ti approcci al C# devi metterti nell'ordine delle idee di pensare come un programmatore C#, senza stare ogni 2x3 a fare paragoni con il Java (che poi, a mio modo di vedere, sarebbe un paragone poco lusinghiero per quest'ultimo).

Sono d'accordo, ma il paragone con java era solo un esempio.

Le interfacce sono dei "contratti": io classe Pippo sottoscrivo questa interfaccia e mi impegno a fornire un'implementazione per tal metodo e/o tale proprietà.
Detto questo, le variabili d'istanza sono dettagli d'implementazione della classe, pertanto non hanno senso all'interno di una interfaccia, in quanto le interfacce NON forniscono implementazione alcuna.
Se tutta una serie di classi condividono certi metodi e certe varibili, evidentemente l'interfaccia non è una soluzione adeguata.
Riguardo alle proprietà, queste non sono delle ivar più evolute. Concettualmente sono cose totalmente diverse che puoi piuttosto associare alla sfilza di getter e setter del Java.

Ma perchè scusa, se al "contratto" aggiungo una variabile comune il contratto diventa "invalido" ?
Continuo a non capire perchè dici che secondo te aggiungere una var. non ha senso e invece aggiungere una proprietà all'interfaccia si...

L'evitare di usare lo stesso nome per più variabili all'interno dello stesso metodo è prima di tutto una buona regola.
Il compilatore non permette i casi che hai indicato, anche se alcuni sarebbero formalmente leciti, per evitare a monte tutta una serie di problemi.

E' una buona regola? Scusa ma chi la dice questa cosa? ...e in base a quale ragionamento sarebbe una buona regola?
Ma poi per curiosità quali sarebbero questi eventuali problemi?
Mai visto qualcuno avere una grana per avere dichiarato lo stesso nome di variabile in blocchi diversi.
Almeno la cosa positiva è che i for con la stessa variabile si possono usare :) (questo non lo avevo provato...).


Nel C# l'aritmetica dei tipi byte, sbyte, short e ushort viene espletata convertendo le variabili a Int32 ed eseguendo l'operazione (dando pertanto un risultato di tipo Int32.
Nei tipi con dimensione maggiore o uguale ad Int32 questo invece non avviene. Quindi due uint puoi sommarli senza che questi vengano convertiti in alcun modo.
Per il discorso dell'overflow, il C# permette di eseguire operazioni checked ed unchecked (la seconda è quella di default).

Si ho capito, però resta il fatto che è un modo pessimo di trattare i dati, così perdi l'utilità di avere dei tipi < di uint, a meno di riempire il codice di cast o di unchecked, come ho detto prima...


https://msdn.microsoft.com/en-us/library/system.windows.input.keyboard.iskeydown(v=vs.110).aspx

Grazie !!!
Ha funzionato anche se ho dovuto importare come assembly references 2 dll (WindowsBase.dll e PresentationCore.dll)...
In ogni caso sempre meglio che usare InteropServices :)


Non capisco quale sia il problema. Davvero.

Quale parte di "perdita di tempo assurda" nella conversione da altri linguaggi non hai capito? :D


A parte che la seconda è una sintassi molto più naturale della prima per dichiarare un array multidimensionale (in quanto prende proprio la forma di una matrice matematica), rimane quanto segue.

Questione di gusti, io preferisco la prima. Il mio disappunto comunque sta nel fatto che hanno scelto un modo diverso di dichiarazione rispetto
al resto dei linguaggi in circolazione...


I delegate sono concettualmente una funzionalità completamente diversa dalle interfacce.
Possono essere usati per espletare funzionalità simili in certi contesti, ma ciò non toglie che stai confrontando pere con mele.

Potresti farmi un esempio semplicissimo di una chiamata a callback che non posso fare con una interfaccia ma solo con un delegate?


Le trovi assurde perchè parti dal preconcetto che il C# DEVE comportarsi come il Java.
Questo è un approccio sbagliato.

Come detto prima java era solo un esempio di paragone (figurati che non è stato neanche il mio primo linguaggio, quindi non ritenermi un fan sfegatato :D).
Continuo a ritenerle assurde perchè alcune cose sono davvero insensate.


Io ti consiglio di prenderti un buon libro di C# e di continuare l'apprendimento senza preconcetti.

Si, lo farò sicuramente.


Il C# è un linguaggio estremamente potente, con una serie di funzionalità ed un framework gigantesco alle spalle (e con quella che è probabilmente la miglior IDE sul mercato).

Per la potenza del C# sono pienamente d'accordo (d'altronde l'ho anche detto io come premessa)...

Riguardo l'IDE... posso dissentire?
Con tutto il rispetto per Visual Studio che è un IDE con i contro***... volevo farti notare che 'di base', NetBeans è molto più avanti di Visual Studio....

Per avere alcune delle funzionalità che ha l'editor di Netbeans ho dovuto scaricare 'appena' tre estensioni aggiuntive...

Te le elenco (giusto per la cronaca :D):
- Productivity Power Tool
- VSCommands for Visual Studio
- Move Line Command

[Kendall]
03-03-2015, 18:46
Ma perchè scusa, se al "contratto" aggiungo una variabile comune il contratto diventa "invalido" ?
Continuo a non capire perchè dici che secondo te aggiungere una var. non ha senso e invece aggiungere una proprietà all'interfaccia si...

Perché, ripeto, la creazione di variabili di istanza è un fatto di implementazione.
E le interfacce non implementano un bel nulla.
Come ti ha detto anche Warduck, se ti serve una classe astratta crei una classe astratta. Le interfacce servono "solo" a dire: Io so fare questo, io so fare quest'altro. Il come farlo dev'essere l'implementazione della classe a dirlo.
Le proprietà hanno senso perché non sono variabili di istanza. Sono computate, alla stregua di un metodo.


E' una buona regola? Scusa ma chi la dice questa cosa? ...e in base a quale ragionamento sarebbe una buona regola?
Ma poi per curiosità quali sarebbero questi eventuali problemi?
Mai visto qualcuno avere una grana per avere dichiarato lo stesso nome di variabile in blocchi diversi.
Almeno la cosa positiva è che i for con la stessa variabile si possono usare :) (questo non lo avevo provato...).

Riutilizzando lo stesso nome all'interno di un metodo, ne ridefinisci il senso, e già di per se questo è concettualmente sbagliato. Siccome di nomi puoi inventarne a iosa, e di ben più legati alla natura della variabile, per quale motivo riutilizzare sempre lo stesso?
Oltre a ciò rendi il metodo meno leggibile, sia per te (nel caso lo rileggessi dopo tempo) sia per gli altri (nel caso tu andassi a rilasciare il tuo codice come opensource).


Si ho capito, però resta il fatto che è un modo pessimo di trattare i dati, così perdi l'utilità di avere dei tipi < di uint, a meno di riempire il codice di cast o di unchecked, come ho detto prima...

Immagino che questo trattamento dei byte e short sia dovuto al fatto che molti processori hanno istruzioni native apposite per le operazioni sugli interi a 32bit.
Per il resto... Deal with it.



Quale parte di "perdita di tempo assurda" nella conversione da altri linguaggi non hai capito? :D

Fosse quello il problema più complesso da trattare nella conversione di codice da un linguaggio all'altro. :rolleyes:


Questione di gusti, io preferisco la prima. Il mio disappunto comunque sta nel fatto che hanno scelto un modo diverso di dichiarazione rispetto
al resto dei linguaggi in circolazione...

Il resto dei linguaggi in circolazione? Quanti saranno mai i linguaggi che usano quella medesima sintassi. A me risulta piuttosto che molti linguaggi supportano la dichiarazione di array multidimensionali come array di array, o array di array di array, e via discorrendo.
A parte questo, comunque, ogni linguaggio fa storia a sé, trovo non porti da nessuna parte fossilizzarsi su meri aspetti estetici.


Potresti farmi un esempio semplicissimo di una chiamata a callback che non posso fare con una interfaccia ma solo con un delegate?

Io infatti ho detto che alcune funzionalità possono essere espletate da entrambi.
Ma ciò non toglie che sono concetti completamente diversi, e che possono essere usate per fare cose molto diverse tra loro.
Un delegate può essere associato ad un puntatore a funzione (a livello concettuale), e sta alla base degli eventi del C#.
Dimmi tu se non sono pere e mele. A mio modo di vedere sono pure pere e bistecche. :-D


Riguardo l'IDE... posso dissentire?
Con tutto il rispetto per Visual Studio che è un IDE con i contro***... volevo farti notare che 'di base', NetBeans è molto più avanti di Visual Studio....

Ti sei approcciato al C#da pochi giorni e già te la senti di fare una simile esclamazione?

whit3noise
03-03-2015, 22:07
Perché, ripeto, la creazione di variabili di istanza è un fatto di implementazione.
E le interfacce non implementano un bel nulla.
Come ti ha detto anche Warduck, se ti serve una classe astratta crei una classe astratta. Le interfacce servono "solo" a dire: Io so fare questo, io so fare quest'altro. Il come farlo dev'essere l'implementazione della classe a dirlo.
Le proprietà hanno senso perché non sono variabili di istanza. Sono computate, alla stregua di un metodo.

Si la soluzione con le classi abstract l'avevo scritta anche io all'inzio.
Comunque, Ok, capito, me ne farò una ragione.


Riutilizzando lo stesso nome all'interno di un metodo, ne ridefinisci il senso, e già di per se questo è concettualmente sbagliato. Siccome di nomi puoi inventarne a iosa, e di ben più legati alla natura della variabile, per quale motivo riutilizzare sempre lo stesso?
Oltre a ciò rendi il metodo meno leggibile, sia per te (nel caso lo rileggessi dopo tempo) sia per gli altri (nel caso tu andassi a rilasciare il tuo codice come opensource).

Continuo a non essere d'accordo col fatto che rende meno leggibile il codice...
...e in base al tuo ragionamento, quindi lo stesso concetto si dovrebbe applicare a più for, in cui invece la stessa variabile, come hai fatto notare tu, si può usare.

Quindi rispetto ad un blocco:

for (int i = 0; i < 100; i ++)
...

for (int i = 10; i < 100; i ++)
...

for (int i = 100; i < 1000; i ++)
...

for (int i = 20000; i >= 0; i --)
...

etc.


...è più leggibile questo ??? :

for (int i = 0; i < 100; i ++)
...

for (int i2 = 10; i2 < 100; i2 ++)
...

for (int altro_nome_con_la_i = 100; altro_nome_con_la_i < 1000; altro_nome_con_la_i ++)
...

for (int __i_con_i_trattini = 20000; __i_con_i_trattini >= 0; __i_con_i_trattini --)
...

for (int i_super = 40000; i_super >= 20; i_super -= 4)
....

etc.


in cui ti devi inventare dei nomi, quando non ti interessa per niente cos'è la variabile, ma ti serve solo per i cicli ?


Immagino che questo trattamento dei byte e short sia dovuto al fatto che molti processori hanno istruzioni native apposite per le operazioni sugli interi a 32bit.
Per il resto... Deal with it.

Al contrario, per implementare l'underflow o l'overflow... lo sforzo che dovevano fare era...... nullo... E' stata una scelta volontaria... :eek:

Ad esempio a livello di assembly se fai una operazione con un registro (per esempio AL [ad 8 bit]) il processore gestisce l'underflow o l'overflow 'automaticamente'...


mov al, 255 # AL = 255
inc al # AL = 0



mov ax, 1234 # AX = 1234
sub ax, 2048 # AX = 64722


etc..


Fosse quello il problema più complesso da trattare nella conversione di codice da un linguaggio all'altro. :rolleyes:

Guarda che non scherzavo... facendo il 'solito' esempio di java, praticamente la conversione è quasi automatica... (a parte quelle cavolo di parentesi quadre...).
In pratica il resto del codice puoi convertirlo proprio con 'CTRL + H'... trova e sostituisci...
Ad esempio per tutte le variabili locali final java (in C# non esiste un concetto simile per le var. locali)... basta cercare final+'spazio' e sostituire con una stringa vuota...
Quando in java trovi arraylist.size (); puoi sostituirlo con arraylist.Count; ... etc. etc..


Il resto dei linguaggi in circolazione? Quanti saranno mai i linguaggi che usano quella medesima sintassi. A me risulta piuttosto che molti linguaggi supportano la dichiarazione di array multidimensionali come array di array, o array di array di array, e via discorrendo.
A parte questo, comunque, ogni linguaggio fa storia a sé, trovo non porti da nessuna parte fossilizzarsi su meri aspetti estetici.

Ma perchè io cosa ho detto?
Forse non sono stato chiaro... parlavo del modo in cui si dichiara un array multidimensionale... ripeto: non capisco perchè non potevano usare la sintassi delle doppie parentesi quadre come fanno gli altri linguaggi, invece di [,] ...


Ti sei approcciato al C#da pochi giorni e già te la senti di fare una simile esclamazione?

Infatti io sto studiando da poco C#, ma visual studio lo conosco da '50' anni :)
E comunque non è una esclamazione... è proprio una constatazione...
Come ti ho scritto prima per avere 'alcune' cose che ha NetBeans ho dovuto aggiungere ben 3 estensioni... perchè di base l'editor non le supportava...

PS:
Ma tu hai visto cosa fanno i plugin che ho scritto sopra?
Se si, mi vuoi dire che l'editor aveva già queste funzioni?

oNaSsIs
04-03-2015, 09:08
Perdona la mia intrusione, ho una conoscenza base del linguaggio C# quindi non me la sento di giudicarlo. Ma...


Comunque, Ok, capito, me ne farò una ragione.

Sbagli a rispondere in questo modo, o altrimenti lasci intendere che in passato tu abbia usato le interfacce in maniera errata, almeno secondo l'OOP.
Come ti è stato già fatto notare le interfacce e le classi astratte sono due cose concettualmente diverse a livello di OOP! Quindi indipendentemente dal linguaggio e dalla sua implementazione. Se qualche altro linguaggio le implementa diversamente, cosa non da escludere, si tratta semplicemente di un linguaggio non puramente OO.

Continuo a non essere d'accordo col fatto che rende meno leggibile il codice...
...e in base al tuo ragionamento, quindi lo stesso concetto si dovrebbe applicare a più for, in cui invece la stessa variabile, come hai fatto notare tu, si può usare.

Quindi rispetto ad un blocco:

for (int i = 0; i < 100; i ++)
...

for (int i = 10; i < 100; i ++)
...

for (int i = 100; i < 1000; i ++)
...

for (int i = 20000; i >= 0; i --)
...

etc.


...è più leggibile questo ??? :

for (int i = 0; i < 100; i ++)
...

for (int i2 = 10; i2 < 100; i2 ++)
...

for (int altro_nome_con_la_i = 100; altro_nome_con_la_i < 1000; altro_nome_con_la_i ++)
...

for (int __i_con_i_trattini = 20000; __i_con_i_trattini >= 0; __i_con_i_trattini --)
...

for (int i_super = 40000; i_super >= 20; i_super -= 4)
....

etc.


in cui ti devi inventare dei nomi, quando non ti interessa per niente cos'è la variabile, ma ti serve solo per i cicli ?
?
Questa soluzione non ti piace?

int i;
for (i = 0; i < 100; i ++)
...

for (i = 10; i < 100; i ++)
...

for (i = 100; i < 1000; i ++)
...

for (i = 20000; i >= 0; i --)

whit3noise
04-03-2015, 17:28
Perdona la mia intrusione, ho una conoscenza base del linguaggio C# quindi non me la sento di giudicarlo. Ma...

No, figurati... non è che questa è una discussione a 2 :)
...anzi sentire più pareri mi fa piacere.


Sbagli a rispondere in questo modo, o altrimenti lasci intendere che in passato tu abbia usato le interfacce in maniera errata, almeno secondo l'OOP.
Come ti è stato già fatto notare le interfacce e le classi astratte sono due cose concettualmente diverse a livello di OOP! Quindi indipendentemente dal linguaggio e dalla sua implementazione. Se qualche altro linguaggio le implementa diversamente, cosa non da escludere, si tratta semplicemente di un linguaggio non puramente OO.

Secondo l'OOP? (Secondo me) è una cosa che si sono 'inventati' in C#... Ti faccio notare che in java è normale avere campi nelle interfacce, e secondo me è anche corretto perchè ti evita di usare una classe abstract 'inutilmente'...

La classe abstract dovrebbe avere senso solo se contiene pure altri metodi (concreti)... Ripeto IMO non è corretto usarle solo perchè devi aggiungere un campo 'comune'.

PS:
Ho risposto che 'me ne farò' una ragione perchè non è che ci sia molto da fare ... :)
Ormai in C# le hanno implementate così le interfacce....


Questa soluzione non ti piace?

int i;
for (i = 0; i < 100; i ++)
...

for (i = 10; i < 100; i ++)
...

for (i = 100; i < 1000; i ++)
...

for (i = 20000; i >= 0; i --)


No, e ti spiego anche perchè...
Lo scopo di dichiarare una variabile in un blocco (o come in questo esempio nei cicli for) è perchè non ti interessa di per sé la variabile, ma ti serve solo in maniera temporanea (variabile di appoggio)... è una soluzione naturalmente quella che hai scritto tu, ma ha lo svantaggio di rendere visibile (anche se localmente) la variabile a tutto il resto del metodo.

Comunque ho un aggiornamento..... (vedere nuovo post sotto :D)...

whit3noise
04-03-2015, 17:46
Aggiornamento:
Ho scoperto (grazie anche al libro che sto leggendo) che uno stesso nome di variabile si può usare in più blocchi :cool:.... anche se... la nuova 'scoperta' è forse peggio della precedente... :D

Questo codice è permesso:

int test = 1;

if (test == 0)
{
int tmp = 112;
Console.WriteLine (tmp);
}
else if (test == 1)
{
int tmp = 113;
Console.WriteLine (tmp);
}
else
{
int tmp = 118;
Console.WriteLine (tmp);
}


Questo invece no (come è giusto che sia):

int test = 1;
int tmp = 102030;

if (test == 0)
{
int tmp = 112;
Console.WriteLine (tmp);
}
else if (test == 1)
{
int tmp = 113;
Console.WriteLine (tmp);
}
else
{
int tmp = 118;
Console.WriteLine (tmp);
}


Errori di comp. sensati perchè la variabile tmp è già dichiarata all'inizio (quindi visibile anche all'interno dei singoli blocchi).

Qual è quindi il problema? :confused:

'Semplicemente' questo... si sono 'inventati' la 'visibilità delle variabili 'inversa' :eek: ...

In pratica, visto che il primo esempio compila... adesso vorrei poter usare lo stesso nome di variabile per fare altre operazioni all'esterno dei blocchi.... e invece non è possibile !!!

...Dichiarando una variabile con lo stesso nome, "dopo" .... ha visibilità anche "prima".... :cry:

Esempio finale (che non compila):

int test = 1;

if (test == 0)
{
int tmp = 112;
Console.WriteLine (tmp);
}
else if (test == 1)
{
int tmp = 113;
Console.WriteLine (tmp);
}
else
{
int tmp = 118;
Console.WriteLine (tmp);
}

// Errore di compilazione :(
int tmp = 123456;
Console.WriteLine (tmp);


Error: A local variable named 'tmp' cannot be declared in this scope because it would give a different meaning to 'tmp', which is already used in a 'child' scope to denote something else :muro: :muro: :muro: :muro: :muro: :muro:

[Kendall]
04-03-2015, 18:33
Secondo l'OOP? (Secondo me) è una cosa che si sono 'inventati' in C#... Ti faccio notare che in java è normale avere campi nelle interfacce, e secondo me è anche corretto perchè ti evita di usare una classe abstract 'inutilmente'...

La classe abstract dovrebbe avere senso solo se contiene pure altri metodi (concreti)... Ripeto IMO non è corretto usarle solo perchè devi aggiungere un campo 'comune'.

PS:
Ho risposto che 'me ne farò' una ragione perchè non è che ci sia molto da fare ... :)
Ormai in C# le hanno implementate così le interfacce....

Tratti il tema con troppa supponenza, senza sapere di quel che parli.
Ora, prenditi un qualsiasi libro di programmazione ad oggetti e studiati per bene la definizione di interfaccia.
Te lo ripeto, le interfacce non contengono implementazione. Non è quello il loro scopo. Ed è anche per questo che non puoi istanziare una interfaccia.
E se conoscessi bene il java sapresti che neppure lui permette (giustamente) di definire variabili all'interno dell'interfaccia.
L'unica cosa che permette è la definizione di costanti statiche...
Ogni campo al suo interno sarà implicitamente public static e final.
E come ben saprai un campo statico non è una ivar.

whit3noise
04-03-2015, 20:27
;42216909']Tratti il tema con troppa supponenza, senza sapere di quel che parli.
Ora, prenditi un qualsiasi libro di programmazione ad oggetti e studiati per bene la definizione di interfaccia.

Ma perchè devi insultare? :(
Piuttosto (sempre se ti va) rispondi alle domande che ti ho fatto prima (es: quelle sui plugins).

;42216909']
Te lo ripeto, le interfacce non contengono implementazione. Non è quello il loro scopo. Ed è anche per questo che non puoi istanziare una interfaccia.
E se conoscessi bene il java sapresti che neppure lui permette (giustamente) di definire variabili all'interno dell'interfaccia.
L'unica cosa che permette è la definizione di costanti statiche...
Ogni campo al suo interno sarà implicitamente public static e final.
E come ben saprai un campo statico non è una ivar.

Eh ???
Ma chi ha parlato di variabili di 'instanza' ???
Forse mi sono espresso male, ma, ovviamente intendevo costanti.
C# non permette di dichiarare variabili con la parola chiave const (!) e questa è una cosa stupida (come detto prima devi usare una classe astratta solo per dichiarare una constante, quando avresti potuto benissimo usare una interfaccia)!

[Kendall]
04-03-2015, 20:50
Ma perchè devi insultare? :(

Non ho offeso nessuno. Rileggi quel che ho scritto.
Mi sembra abbastanza appurato che tu stia trattando il tema con fin troppa presunzione, senza aver ben chiaro alcuni concetti fondamentali della OOP.


Piuttosto (sempre se ti va) rispondi alle domande che ti ho fatto prima (es: quelle sui plugins).

C'è poco da rispondere. Tu reputi una IDE inferiore perché ti devi installare alcuni plugin per ottenere delle feature specifiche che ti interessano (plugin che appunto esistono, quindi non vedo dove stia il problema).
Comunque se reputi Netbeans uno strumento superiore non è certo mia intenzione farti cambiare idea (io per esempio nella programmazione Java mi trovo più a mio agio con IntelliJ).


Eh ???
Ma chi ha parlato di variabili di 'instanza' ???
Forse mi sono espresso male, ma, ovviamente intendevo costanti.
C# non permette di dichiarare variabili con la parola chiave const (!) e questa è una cosa stupida (come detto prima devi usare una classe astratta solo per dichiarare una constante, quando avresti potuto benissimo usare una interfaccia)!
Qui stai rivoltando la frittata. Tu hai parlato di variabili fin dal primo post e da come ne parlavi era abbastanza palese che ti riferissi proprio a quelle.
Comunque se hai altri dubbi sul C# sarò felice di risponderti, ma continuare a spiegarti (e non sono stato l'unico) dei concetti se dall'altra parte non c'è verso di voler ascoltare non porta da nessuna parte.

71106
08-03-2015, 10:19
Non ho letto il resto del thread ma in generale mi trovo piuttosto d'accordo con il post iniziale, che ho letto interamente.

E' da un po' di anni ormai che ritengo che C# sia un immondezzaio; è partito come un linguaggio innovativo e produttivo e sul bleeding edge della tecnologia, accusato di aver copiato da Java e tuttavia così migliore di Java; e quando ancora ero troppo ignorante per sapere come dovrebbe essere fatto un vero linguaggio di programmazione (era il 2000, facevo il liceo...) ci credevo.

Poi lui si è evoluto in maniera sempre più idiota e io nel frattempo mi sono specializzato in linguaggi formali all'università, da cui la mia attuale conclusione: fa cagare. :D

Di seguito i miei commenti.


[PS: scusate se il post è troppo lungo] Assolutamente, figurati. :)


1) Interfacce
Non è possibile inserire variabili nelle interfacce... Ma per quale cavolo di motivo ???
Se ho delle classi che implementano tutte la stessa interfaccia e che usano tutte una stessa variabile,
devo definire n volte la variabile in tutte le classi ???
Ok, è risolvibile facendo estendere alle classi una classe abstract invece di implementare una interfaccia...
...ma allora dico io... le potevano eliminare proprio queste interfacce... No? Mi trovi d'accordo solamente sull'ultima frase.

Se le interfacce potessero anche contenere variabili membro sarebbero un po' troppo simili alle classi astratte e perderebbero il loro senso di interfaccia. Ci si possono inserire proprietà, ma si tratta di uno zucchero sintattico che equivale a inserire due metodi, un getter e un setter; i dati sottostanti a cui la proprietà fa riferimento non vengono inseriti, l'onere della loro gestione resta alla classe implementante.

Sono totalmente d'accordo che le interfacce siano una parziale ridondanza e che in un moderno linguaggio di programmazione dovrebbero essere rimosse (insieme a tante altre cose) in favore di un sistema di tipi completamente inferito/duck e statico.


2) Scope delle variabili locali. [...] Questa neanche la sapevo ma se è così è allucinante.

Più sopra ho scritto che "C# si è evoluto in maniera idiota". Questo è uno dei risultati del fenomeno a cui mi riferisco.

Se vai a leggere qualche intervista agli autori di questa pattumiera di linguaggio trovi frequenti riferimenti al fatto che loro decidono le feature del linguaggio in funzione di cosa sembra migliorare la produttività degli sviluppatori. Il risultato potrà piacere a molti, ma non è informatica e a me fa schifo.


3) Trattamento orribile delle operazioni con i tipi primitivi Probabilmente te l'hanno già detto, c'è stato un fraintendimento da parte tua. Il compilatore non ti accusa di voler convertire un byte a int, ma di voler convertire un int a un byte (operazione che può causare una perdita di informazione).

Non ho esperienza in merito, ma questo è ciò che devi provare:


byte b1 = (byte)10;
byte b2 = (byte)20;
byte b3 = b1 + b2;


Niente cast sulla terza istruzione.


Premessa:
Principalmente uso java, ma il motivo principale per cui ho voluto provare C# è il supporto dei tipi unsigned che in java mancano...
Tralascio ovviamente la 'porcheria' che hanno fatto in Java 8 creando delle classi per 'fare operazioni' su variabili invece che tipi primitivi per sopperire a tale mancanza... Sono immensamente d'accordo su tutto questo pezzo. Devo ancora trovare UN cacchio di linguaggio di programmazione il cui sistema di tipi supporti TUTTI i principali insiemi numerici normalmente trattati in matematica: N, Z, Q, R, C (naturali, interi, razionali, reali, complessi). Tecnicamente essi sono facilmente rappresentabili come (rispettivamente):

interi senza segno,
interi con segno in complemento a due,
coppie di interi senza segno più un flag di segno,
numeri in virgola mobile,
coppie di numeri in virgola mobile.



4) Uso obblicatorio di chiamate a DLL per alcuni task in un linguaggio 'moderno' di alto livello ??? Qui sono d'accordo solo in parte. Una carenza delle librerie disponibile non è da imputare al linguaggio, ed è qualcosa che può comunque essere risolta in futuro.


5) Dichiarazione array [...] Sono in disaccordo. Ogni linguaggio di programmazione ha il diritto di avere la propria sintassi. Che male c'è a scrivere "[,]" al posto di "[][]"? Se questo è un problema allora che ne pensi della agghiacciante sintassi usata in Objective-C per invocare i metodi? :asd:


6) Delegate e Interfacce [...] La tua confusione qui è totalmente comprensibile, questa è una sonora ridondanza nonchè uno dei risultati dell'introdurre feature a merda solo perchè hai osservato una massa di cerebrolesi diventare più produttivi in quel modo.

Di nuovo, questa non è informatica, è un ammasso di cazzate. Il fatto che Microsoft ci faccia una montagna di soldi è solo un ulteriore motivo di perdita di fiducia nell'umanità.

lishi
08-03-2015, 12:17
zip

lishi
08-03-2015, 12:51
Ciao a tutti, scrivo qui per avere il vostro parere (e anche per sfogarmi un po'...). [PS: scusate se il post è troppo lungo]

Sono passato da circa 2 giorni a C# e globalmente devo dire che è un buon linguaggio... ma ci sono alcune cose che non riesco proprio a digerire.

Scrivo solo quelle che ho trovato finora, ma sicuramente ce ne saranno altre...

1) Interfacce
Non è possibile inserire variabili nelle interfacce... Ma per quale cavolo di motivo ???
Se ho delle classi che implementano tutte la stessa interfaccia e che usano tutte una stessa variabile,
devo definire n volte la variabile in tutte le classi ???
Ok, è risolvibile facendo estendere alle classi una classe abstract invece di implementare una interfaccia...
...ma allora dico io... le potevano eliminare proprio queste interfacce... No?

PS:
la cosa assurda è che invece le proprietà (che sono "più evolute") si possono inserire... Mah...



Ti hanno già risposto, dettagliamene, Ma puoi risolvere la cosa semplicemente dichiarando una static class e mettere delle costanti li.

Mettere una variabili come dici tu in una interfaccia non ha vantaggi dal punto di vista dell'interfaccia.
Le proprietà invece hanno senso hanno uno scopo diverso, se avrai guardato un po i contenitori .net avrai certamente notato la proprietà Count. In Java o c++ sarebbe stato Count() è sostanzialmente una funzione.


2) Scope delle variabili locali.
Che fine hanno fanno le regole di scoping che gli umani conoscevano fino ad adesso (perlomeno nei linguaggi C-like) ??? :eek:
Questa è davvero fastidiosa. :mad:

Questo codice non compila:

for (int i = 0; i < 10; i ++)
Console.WriteLine ("i = " + i);

int i = 911;
Console.WriteLine ("i = " + i);


Stessa cosa per questo:

{
int i = 113;
Console.WriteLine ("i = " + i);
}

int i = 118;
Console.WriteLine ("i = " + i);


Error: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else.

...Ho pensato: forse allora funziona come Javascript... :confused:
Nel primo esempio, pensavo che la i dentro il for fosse visible 'fuori' il for...

for (int i = 0; i < 10; i ++)
Console.WriteLine ("i = " + i);

// int i = 911;
Console.WriteLine ("i = " + i);


...e invece:
The name 'i' does not exist in the current context.

Senza parole: Non è possibile più usare lo stesso nome di variabile anche se si trova in blocchi diversi... :Puke:



Si ho notato anche io questa cosa, ogni tanto mi ha dato fastidio, ma visto che


for (int i = 0; etc
{}
for (int i = 0; etc
{}



Va sono casi proprio rari. preferisco tenere le mie funzioni corti in qualunque caso.

Un po come nello switch pure nel case default (o ultima della lista) devi mettere il break. Si sopravvive.



3) Trattamento orribile delle operazioni con i tipi primitivi

Premessa:
Principalmente uso java, ma il motivo principale per cui ho voluto provare C# è il supporto dei tipi unsigned che in java mancano...
Tralascio ovviamente la 'porcheria' che hanno fatto in Java 8 creando delle classi per 'fare operazioni' su variabili invece che tipi primitivi per sopperire a tale mancanza...

Per risolvere il problema in java il metodo migliore è semplicemente dichiarare tutte le variabili int, ed usare l'operatore & con la maschera appropriata.

Esempi:
se mi serve una variabile 'unsigned byte' (8 bit) la dichiaro int e uso ad es: x = (x + 10) & 0xFF;
se mi serve una variabile 'unsigned short' (16 bit) la dichiaro int e uso ad es: x = (x + 10) & 0xFFFF;
... ecc.

Bene...
Pensavo che passando a C# il problema dei tipi unsigned fosse una volta per tutte risolto, fino a quando non scopro come tratta le operazioni...

Davo per scontato che C# gestisse automaticamente l'overflow e l'underflow del valore delle variabili... povero illuso... :(

Come al solito questo esempio non compila:

byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2;


Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)
Coosa ??? :what: Ti sto dicendo io che sono tutti byte e cerchi di convertire i valori ad int ????

Conclusione:
Problema della 'sporcizia' del codice non risolto (quindi come java)... perchè praticamente bisogna riempire tutto il codice di cast...
o comunque usare la 'stessa tecnica' dell'"and" di java... :Puke: :incazzed:

Per compilare si deve eseguire obbligatoriamente un cast...

byte b3 = (byte) (b1 + b2)


Ho fatto l'esempio con i tipi unsigned ma lo stesso vale anche per i tipi signed.



ti hanno già risposto



4) Uso obblicatorio di chiamate a DLL per alcuni task in un linguaggio 'moderno' di alto livello ???
Penso che sicuramente ci saranno molti altri casi, io descrivo un semplice problema che mi è capitato...

Volevo semplicemente leggere gli eventi keyDown e keyUp in un form (in pratica mi interessava ottenere il KeyCode dei tasti).
Tutto bene fino a quando non mi accorgo che tramite API/metodi/campi 'normali' di C# non c'è modo di distinguere per i tasti modificatori (Shift, Ctrl e Alt) se
il tasto si trova a sinistra o destra.

Apparentemente (cercando anche in 'giro') l'unico modo è di usare System.Runtime.InteropServices.DllImport importando la dll user32.dll e usando la chiamata
GetAsyncKeyState... ...bruttissimo... :grrr:



Francamente sarei più preoccupato che devo chiamare le funzioni win32 per leggere un file ini piuttosto che dover sapere se è stato lo shift destro o shift sinistro.

La realtà è che DllImport è una una tua amica. Eventualmente dovrai usarla se vuoi fare queste cose particolari. Sarebbe bello che gli progettatori avessero pensato a tutto ma non ho ancora trovato una libreria cosi completa.



5) Dichiarazione array
Ok, questo non è un vero problema, ma è veramente una cosa antipatica e soprattutto una perdita di tempo assurda.

Vorrei capire perchè è stato scelto di dichiarare un array con le parentesi quadre da inserire obbligatoriamente prima del nome dell'array e non continuare ad
usare la sintassi opposta (come tutti i linguaggi C-Like), o comunque se era 'proprio necessario', supportarle entrambe. :bsod:

Vi dico questo perchè mi sono accorto che, quando devo convertire dei pezzi di codice (scritti ad. es. in C/C++/Java) in C# perdo più tempo ad invertire l'ordine
delle parentesi quadre rispetto a sistemare il resto degli errori. :muro:

Un'altra cosa incompresibile è perchè non si può dichiarare un array bidimensionale come:
int [][] array = new int [10][20];

...ma invece si deve per forza usare:
int [,] array = new int [10, 20]; :nono:




scritta come vuoi tu è un array di array. Dove ogni array potrebbe avere una differente lunghezza. che è assolutamente diverso dalla matrice che vuoi creare.
infatti questo si compila

int[][] a = new int[100][];
a[0] = new int[100];
a[1] = new int[101];
a[2] = new int[102];



6) Delegate e Interfacce
Devo ancora approfondire meglio l'argomento... quindi premetto che può essere una mia mancanza,
ma non riesco davvero a capire perchè devo usare i delegate quando posso fare benissimo la stessa cosa con le interfacce... :boh:
Qualcuno può spiegarmelo?



Convenienza e leggibilità del codice.

per esempio

evento += funzione;
sarebbe diventato
evento += this;

e avresti dovuto aggiungere una interfaccia alla tua classe senza magari che avessi voluto intenzione farlo.

Altrimenti avresti dichiarato una classe da qualche parta che implementava interfaccia derivata(o una classe anonima) , e fatto
evento += new Pippo();

Ovviamente avresto dovuto prima salvarlo da qualche parte se volevi avevi bisogno di eventualmente rimuovere evento

_ciccio = new Pippo();
evento += _ciccio.

Mentre ovviamente un ide moderno ti avrebbe potuto evitare di fare tutta la creazione e generare automaticamente tutto non toglie che avrebbe riempito il codice di roba inutile se non per collegare evento.

Particolarmente visto che gli delegate sono profondamente legati ai lambda sono incredibilmente utili. sopratutto se vuoi usare Linq



Per ora mi fermo qui... Ripeto queste sono cose (secondo me assurde) che ho trovato in appena due giorni di utilizzo di C#;
se ne trovo altre le scriverò...

Aspetto vostri commenti.

Ci sono problemi nel linguaggio c#. non è perfetto, ci sono vantaggi e svantaggi rispetto alle alternative. Francamente non penso che quelli elencati tu siano svantaggi gravi.

Anzi, alcune sono dovute perché è un linguaggio più completo.

WarDuck
08-03-2015, 22:58
Sono totalmente d'accordo che le interfacce siano una parziale ridondanza e che in un moderno linguaggio di programmazione dovrebbero essere rimosse (insieme a tante altre cose) in favore di un sistema di tipi completamente inferito/duck e statico.


BOOM!!!

Le interfacce rappresentano il fondamento dell'object oriented e di tutto lo sviluppo fatto "non ad-minchiam". Formano un contratto tra le varie parti in causa, e tutti i sistemi dovrebbero comunicare conoscendo solo ed esclusivamente le interfacce, questo se parliamo naturalmente di linguaggi object oriented.

Probabilmente è proprio perché la gente non capisce le interfacce, che di fatto rappresentano il più alto grado di astrazione tra componenti, che molti programmatori della domenica non sanno cosa farsene.

Dopodiché il sistema di tipi inferito e statico mi pare sia una caratteristica di C#, oltre che di C++11 ad esempio.


Il risultato potrà piacere a molti, ma non è informatica e a me fa schifo.

BOOM!!!

Ogni tanto arriva qualcuno in questo forum e se ne esce fuori pontificando su cosa è o cosa non è informatica, manco fosse Dijkstra.

Non so se ridere o se piangere di questo, specialmente perché interventi come il tuo arrivano a "gamba tesa" su una conversazione che già di per se lascia il tempo che trova.

Giudicare un linguaggio dall'apparenza, mentre lo si sta ancora apprendendo e senza magari averlo usato veramente lascia il tempo che trova.


Devo ancora trovare UN cacchio di linguaggio di programmazione il cui sistema di tipi supporti TUTTI i principali insiemi numerici normalmente trattati in matematica: N, Z, Q, R, C (naturali, interi, razionali, reali, complessi). Tecnicamente essi sono facilmente rappresentabili come (rispettivamente):

interi senza segno,
interi con segno in complemento a due,
coppie di interi senza segno più un flag di segno,
numeri in virgola mobile,
coppie di numeri in virgola mobile.


Non capisco la tua affermazione. Tanto per dirne uno: Python.

Ma anche C++ (vedi header complex e ratio).


La tua confusione qui è totalmente comprensibile, questa è una sonora ridondanza nonchè uno dei risultati dell'introdurre feature a merda solo perchè hai osservato una massa di cerebrolesi diventare più produttivi in quel modo.

Di nuovo, questa non è informatica, è un ammasso di cazzate. Il fatto che Microsoft ci faccia una montagna di soldi è solo un ulteriore motivo di perdita di fiducia nell'umanità.

Diciamo che il tuo linguaggio non aiuta a fare una buona impressione.

Chiacchere da bar fatte tanto per inzozzare un thread e buttarla in caciara.

Ti chiederei di argomentare, ma non voglio far andare il topic più a schifio di come già è andato.