2014-10-17 6 views
22

Ecco un codice che mi disturba ogni volta che ci penso.VB vs C#: perché è possibile?

Option Strict On 

Module Module1 

    Sub Main() 
     For Each i As Integer In New String() {"why", "is", "this", "tolerated?"} 
      ' compiles just fine. 
     Next 
    End Sub 

End Module 

C# semplicemente non permetterà la conversione di stringhe di numeri interi in modo implicito.

class Program { 
    static void Main(string[] args) { 
     foreach (int i in new string[] {"that's", "better"}) { 
      // will not compile, and for good reason. 
     } 
    } 
} 

Perché VB Facciamolo? Sto cercando di divertirmi con questo perché sono ancora relativamente nuovo qui, ma sono anche sinceramente curioso. Sono sicuro che ci sono degli sviluppatori là fuori con la risposta.

+1

Ho incluso l'istruzione 'Option Strict' nel post e si suppone che limiti le conversioni di tipo all'ampliamento delle conversioni e impedisca la digitazione implicita, eppure continua a compilarlo. – scottyeatscode

+4

@mellamokb, come mostrato dall'OP, funziona anche con 'Option Strict On'. – jmcilhinney

+0

Questo è un buon punto. Secondo [questo post del blog] (http://www.owenpellegrin.com/articles/vb-net/converting-strings-to-numbers/) anche con 'Option Strict Off' non dovrebbe consentire la conversione implicita di stringhe che sono valori numerici non validi, quindi qualcos'altro deve succedere qui.** EDIT **: l'ho appena testato con LINQPad e non sembra compilare ... dove stai testando questo in cui non ottieni errori del compilatore? – mellamokb

risposta

14

Sembra essere un idiosincrasia della dichiarazione For Each. Secondo la documentazione viene valutato in fase di runtime.

Da Link:

Quando Option Strict è impostato su On, restringendo le conversioni di solito causano errori di compilazione. In un'istruzione For For Each, tuttavia, le conversioni dagli elementi di gruppo a elemento vengono valutate ed eseguite in fase di esecuzione e gli errori del compilatore causati dal restringimento delle conversioni vengono soppressi.

Nell'esempio seguente, l'assegnazione di m come valore iniziale per n non viene compilata quando Option Strict è attiva perché la conversione da Long a un intero è una conversione a restringimento. Nell'istruzione For Each, tuttavia, non viene segnalato alcun errore del compilatore, anche se l'assegnazione al numero richiede la stessa conversione da Long a Integer. Nell'istruzione For Each che contiene un numero elevato, si verifica un errore di runtime quando ToInteger viene applicato al numero elevato.

+2

Eccellente! Grazie, Marco! – scottyeatscode

+1

Prego, domanda interessante. –

+8

Wow - proprio quando pensavo di aver visto tutto fino a quando la stranezza di VB va ... –

6

Come supplemento alla risposta di Mark, ecco come appare il codice compilato vb.net. Come si può vedere il codice è compilato in una dichiarazione For...Next e l'errore si verifica solo in fase di esecuzione quando si tenta di convertire la stringa in numero intero.

Dim VB$t_array$L0 As String() = New String() { "why", "is", "this", "tolerated?" } 
Dim VB$t_i4$L0 As Integer 
For VB$t_i4$L0 = 0 To VB$t_array$L0.Length - 1 
    Dim i As Integer = Conversions.ToInteger(VB$t_array$L0(VB$t_i4$L0)) 
Next VB$t_i4$L0 
+0

Come sei riuscito a vedere in che modo il codice è diventato così? Non riesco a farlo in Reflector 8. – scottyeatscode

+0

Se si dispone dell'applicazione desktop, si dovrebbe essere in grado di trascinare e rilasciare il file eseguibile sulla vista ad albero dell'assieme. –

+0

Tutto sembra molto leggibile per me e in C#. È così che appare la decompilazione dopo l'offuscamento? – scottyeatscode

11

Microsoft si scusa per questo nella specifica del linguaggio, il capitolo 10.9:

L'elemento corrente dell'iterazione viene convertito nel tipo della variabile di controllo del ciclo, anche se la conversione è esplicito perché non c'è nessun posto conveniente per introdurre un operatore di conversione nella dichiarazione. Questo è diventato particolarmente problematico quando si lavora con il tipo di raccolta più comune, System.Collections.ArrayList, perché il suo tipo di elemento è Object. Questo avrebbe richiesto lanci in moltissimi loop, qualcosa che sentivamo non era l'ideale.

Ironicamente, i generici hanno consentito la creazione di una raccolta fortemente tipizzata, System.Collections.Generic.List (Of T), che avrebbe potuto farci ripensare a questo punto di progettazione, ma per motivi di compatibilità, non può essere modificato ora.

0

io sono l'unico che può vedere che nel codice VB la matrice è un generico (variante) di array, mentre il codice C# contiene rigorosa matrice di stringhe?

+1

Ho aggiornato il codice in modo che siano entrambi "string string array". Il codice mostra ancora errori di tempo di compilazione. Mark Hall, Bjorn-Roger Kringsja e Hans Passant hanno già fornito più di informazioni sufficienti per spiegare perché questo comportamento si verifica. – scottyeatscode

+0

Infatti, se si guarda la risposta di Bjorn-Roger Kringsja, l'elenco di stringhe diventa in definitiva una serie di stringhe. – scottyeatscode