Na
primeira parte do artigo, o tópico superioridade do VB.NET sobre o C # em termos de classificação do TIOBE encontrou uma resposta animada nos comentários. Portanto,
seguindo os
conselhos do AngReload, vamos analisar as
tendências do StackOverflow.

C # ainda é forte! A revolução de que se falou há tanto tempo foi cancelada! Viva, camaradas! Ou não? A classificação TIOBE é baseada em consultas de mecanismos de pesquisa e a classificação SO é baseada em tags de perguntas feitas. Talvez os desenvolvedores do VB.NET, que incluem muitas pessoas que não têm especialidades, simplesmente não conheçam a existência do StackOverflow? Ou, tendo chegado lá pelo Google, ou mesmo pelo Bing, não entende como fazer uma pergunta? Ou talvez eles tenham documentação suficiente da Miscrosoft e todas as poucas perguntas já tenham sido respondidas.
De uma maneira ou de outra, a participação do VB.NET é perceptível e estável, embora não em primeiro lugar em termos de volume. E, é claro, esse resultado não teria sido possível sem uma equipe forte de designers e desenvolvedores de idiomas. Abaixo está a segunda parte da tradução de um artigo por um membro dessa equipe,
Anthony Green .
Conteúdo
Conversões
34. Transformações booleanas
A conversão de
Boolean True
para qualquer tipo numérico assinado gera
-1
e, para qualquer tipo não assinado, fornece o valor máximo para esse tipo, enquanto que em C # não existem essas conversões. No entanto, o método
Convert.ToInt32
, por exemplo, converte
True
em
1
e é assim que ele é representado com mais freqüência em
IL
. Na direção oposta, qualquer número diferente de
0
é convertido em
True
.
Porque O motivo pelo qual o VB prefere usar de
-1
a
1
é porque a negação bit a bit de 0 (todos os bits estão definidos como 0) em qualquer idioma é
-1
(todos os bits estão definidos como
1
); portanto, esse valor combina lógica e bit a bit operações como
And
,
Or
e
Xor
.
Conversões de e para as linhas "Verdadeiro" e "Falso" também são suportadas (é claro, não diferenciam maiúsculas de minúsculas).
35. As conversões entre os tipos de Enum, bem como entre os tipos de Enum e seus tipos de base, são completamente ilimitadas, mesmo se Option Strict estiver definido como On
Do ponto de vista filosófico, uma linguagem refere-se a tipos de
Enum
e não a um conjunto de constantes nomeadas de um tipo inteiro básico. O lugar onde isso é mais óbvio é a igualdade. É sempre permitido comparar qualquer número inteiro com um valor de enumeração, enquanto que em C # isso gera um erro.
Hora da história: A API da Roslyn passou por muitas revisões internas. Mas em cada um deles, uma enumeração
SyntaxKind
foi alocada para cada idioma, o que informa qual sintaxe o nó representa (por exemplo,
IfStatement
,
TryCastExpression
). Uma vez, um desenvolvedor usou uma API que tentou abstrair do idioma e retornou um dos valores
SyntaxKind
, mas apenas como
Integer
, e sem receber erros ao comparar
Integer
bruto e
SyntaxKind
, esse desenvolvedor veio imediatamente ao meu escritório e reclamou:
“int is detalhes de implementação, eu deveria ter sido forçado a fazer um elenco! ” .
Ao longo dos anos, durante a próxima revisão da API, removemos completamente as propriedades (
Property Kind As SyntaxKind
), que apontavam para um tipo específico de idioma, e todas as APIs começaram a retornar
Integer
. Todo o código C # quebrou e todo o código VB continuou a funcionar como se nada tivesse acontecido.
Um pouco mais tarde, decidimos renomear essa propriedade para
RawKind
e adicionar métodos de extensão específicos do idioma
Kind()
. Todo o código C # quebrou porque eram necessários parênteses para chamar métodos, mas, como não eram necessários no VB, todo o código VB continuou a funcionar novamente como se nada tivesse acontecido.
36. A verificação de estouro / estouro negativo para aritmética inteira é completamente controlada pelo ambiente de compilação (configurações do projeto), mas VB e C # usam valores padrão diferentes; no VB, a verificação de estouro é ativada por padrão
Tipos integrais têm um intervalo; portanto, por exemplo, o
Byte
pode representar valores de 0 a 255. Então, o que acontece quando você adiciona o
Byte
1 ao
Byte
255? Se a verificação de estouro / estouro estiver desativada, o valor será rolado para 0. Se o tipo for assinado, ele será rolado para o número negativo mais baixo (por exemplo, -128 para
SByte
). Provavelmente isso indica um erro no seu programa. Se a verificação de estouro / estouro estiver ativada, uma exceção será lançada. Para entender o que quero dizer, dê uma olhada nesse loop
For
inofensivo.
Module Program Sub Main() For i As Byte = 0 To 255 Console.WriteLine(i) Next End Sub End Module
código fonte do githubPor padrão, esse loop lançará uma exceção no VB (uma vez que a última iteração do loop ultrapassa a borda
Byte
. Mas com a verificação de estouro desativada, ele faz um loop porque depois de 255 i se torna 0 novamente.
Subfluxo é a situação oposta ao subtrair abaixo do valor mínimo para o tipo, resultando no valor máximo.
Uma situação de estouro mais comum é simplesmente a adição de dois números. Pegue os números 130 e 150, ambos como
Byte
. Se você reuni-los, a resposta é 280, que não se encaixa no Byte. Mas seu processador não percebe isso. Em vez disso, ele relata que a resposta é 24.
A propósito, isso não tem nada a ver com conversões. Adicionar dois bytes fornece um byte; é assim que a matemática binária funciona. Embora você também possa exceder executando uma conversão, por exemplo, ao tentar converter Longo em Inteiro. Sem verificar se há transbordamento, o programa simplesmente corta os bits e os materiais extras, tanto quanto se encaixa nessa variável.
Qual a diferença? Performance. A verificação do CLR quanto ao estouro requer um tempo computacional um pouco mais comparado à opção sem verificação, como todas as outras verificações de segurança. O VB é baseado na filosofia de que a produtividade do desenvolvedor é mais importante que o desempenho computacional; portanto, por padrão, você tem a verificação de segurança ativada. A equipe de desenvolvimento de C #
hoje pode tomar uma decisão diferente sobre as configurações padrão do projeto, mas, considerando que os primeiros desenvolvedores de C # vieram de desenvolvedores de C / C ++, esse grupo de pessoas provavelmente exigiria que o código não fizesse mais nada, o que poderia custar ciclos do processador ;
essa é uma diferença filosófica difícil .
Nuance: mesmo se a verificação de estouro / estouro estiver desativada, a conversão dos valores
PositiveInfinity
,
NegativeInfinity
,
NaN
de
Single
ou
Double
em
Decimal
lançará uma exceção, pois nenhum desses valores pode, em princípio, ser representado em decimal.
37. A conversão de números de ponto flutuante em tipos inteiros utiliza arredondamentos de banqueiros em vez de truncar
Se você converter 1,7 para um número inteiro em VB, o resultado será 2. Em C #, o resultado será 1. Não posso dizer nada sobre regras matemáticas fora dos Estados Unidos, mas quando alterno de um número real para um número inteiro, arredondo instintivamente. E nenhum daqueles que conheço fora do círculo de programadores acredita que o número inteiro mais próximo de 1,7 é 1.
Na verdade, existem vários métodos de arredondamento, e o tipo de arredondamento usado no VB (e no método Math.Round) é chamado arredondamento de banco ou arredondamento estatístico por padrão. Sua essência é que, para um número no meio entre dois números inteiros, VB arredonda para o número par mais próximo. Portanto, 1,5 é arredondado para 2 e 4,5 é arredondado para 4. O que realmente não funciona da maneira como fomos ensinados na escola - fui ensinado a arredondar para 0,5 (tecnicamente, arredondar para o lado a partir do zero). Mas, como o nome indica, o arredondamento bancário tem a vantagem de que, com um grande número de cálculos, você se divide ao arredondar ao meio e nem sempre cede ou sempre guarda dinheiro. Em outras palavras, em um conjunto grande, isso limita a distorção dos dados ao desvio estatístico final.
De onde vem a diferença? O arredondamento é mais intuitivo e prático, truncando mais rapidamente. Se você considerar usar o VB em aplicativos LOB, e especialmente em aplicativos como as macros do Excel executadas no VBA, simplesmente largar casas decimais pode causar ... problemas.
Eu acho que é óbvio que o método de conversão é sempre uma questão controversa e deve ser indicada explicitamente, mas se você precisar escolher uma única ...
38. Não é um erro converter classes NotInheritable para / de interfaces que elas não implementam em tempo de compilação
De um modo geral, se você estiver verificando uma classe NonInheritable para uma implementação de interface, poderá entender em tempo de compilação se essa conversão é possível porque você conhece todas as interfaces desse tipo e todos os seus tipos básicos. Se o tipo é herdado, você não pode ter certeza de que essa conversão é impossível, porque o tipo do objeto de tempo de execução mencionado pode de fato ter um tipo mais derivado que implementa essa interface. No entanto, há uma exceção devido à interoperabilidade COM, quando, em tempo de compilação, pode não ser visível que o tipo tenha algo a ver com a interface, mas, em tempo de execução, ocorrerá. Por esse motivo, o compilador VB gera um aviso nesses casos.
Porque VB e COM cresceram juntos quando eram crianças no bairro antigo. Portanto, existem várias soluções no design de linguagem nas quais o VB presta muita atenção às coisas que existiam apenas no COM no momento do lançamento do .NET 1.0.
39. Tentar descompactar (unbox) null em um tipo significativo resulta em um valor padrão do tipo, não em NullReferenceException
Eu acredito que tecnicamente isso também é verdade para tipos de referência, mas sim:
CInt(CObj(Nothing)) = 0
Porque Porque
CInt(Nothing) = 0
, e o idioma tende a ser um pouco consistente, independentemente de você ter digitado suas variáveis ou não. Isso se aplica a qualquer estrutura, não apenas aos tipos significativos internos. Veja o
raciocínio em # 25 para mais detalhes.
40. O desempacotamento suporta conversões de tipo primitivo
Tanto em VB quanto em C #, você pode converter
Short
em
Integer
, mas e se você tentar converter
Short
em
Integer
? Em VB
Short
será primeiro descompactado e depois convertido em
Integer
. Em C #, a menos que você descompacte manualmente antes de converter para
int
, uma
InvalidCastException
será lançada.
Isso se aplica a todas as conversões internas, ou seja, tipos numéricos compactados, conversões entre strings e tipos numéricos, strings e datas (sim, decimal e data são tipos primitivos).
Porque Novamente, para garantir um comportamento consistente, independentemente de seu programa ser totalmente digitado, digitado como Objeto ou ser refatorado de uma opção para outra. Veja o
item 39 acima.
41. Há conversões entre String
e Char
String
convertida em Char
, representando seu primeiro caractere.Char
convertido em String
única maneira razoável.
Porque ninguém, exceto eu, se lembra da sintaxe de um caractere literal no VB (e não deveria).
42. Há conversões entre as String
e Char
String
convertida em uma matriz Char
consiste em todos os seus caracteres.- A matriz
Char
é convertida em uma String
consiste em todos os seus elementos.
Por definição: essas transformações criam novos objetos, você não obtém acesso à estrutura
String
interna.
História engraçada: Uma vez encontrei (ou talvez o relatei e estava pesquisando) quebrando alterações entre o .NET 3.5 e 4.0, porque entre essas versões a equipe do .NET adicionou o modificador
ParamArray
ao segundo
String.Join
sobrecarga
String.Join
, que utiliza uma matriz de strings . As suposições exatas são perdidas no tempo (provavelmente para melhor), mas, como acredito, o motivo é que, com o modificador
ParamArray
agora você pode converter uma matriz
Char
em uma string e passá-la como um elemento separado para a matriz de parâmetros. Tema divertido.
43 e 44. Conversões de String para tipos numéricos e de data suportam sintaxe literal (normalmente)
CInt("&HFF") = 255
CInt("1e6") = 1_000_000
CDate("#12/31/1999#") = #12/31/1999#
Isso funciona com prefixos de base e torna possível usar uma maneira muito conveniente de converter entrada hexadecimal (ou octal) em um número:
CInt("&H" & input)
. Infelizmente, essa simetria está se degradando no momento da redação deste artigo, porque o tempo de execução do VB não foi atualizado para oferecer suporte ao prefixo binário & B ou ao
1_000
grupo de
1_000
dígitos, mas espero que isso seja corrigido na próxima versão. A notação científica funciona, mas sem sufixos de tipo, e as conversões de data também suportam formatos de data padrão; portanto, o formato JSON usado na ISO-8601 também funciona:
CDate("2012-03-19T07: 22Z") = #3/19/2012 02:22:00 AM#
.
Porque Não conheço outro motivo senão conveniência. Mas eu
realmente gostaria de oferecer suporte a outros formatos comuns quase onipresentes na rede hoje, como #FF, U + FF, 0xFF. Eu acho que isso poderia facilitar muito a vida em alguns tipos de aplicações ...
45. NÃO conversões entre Char
e tipos inteiros
O QUE?!?!?Depois de ler sobre todas essas transformações adicionais, você está surpreso? O VB proíbe conversões entre
Char
e
Integer
:
CInt("A"c)
não compila.CChar(1)
não compila.
Porque Não está claro o que vai acontecer. Geralmente, o VB nessas situações usa uma abordagem pragmática e / ou intuitiva, mas para a expressão
CInt("1")
, acho que metade dos leitores esperaria o número 1 (valor do caractere 1) e metade esperaria o número 49 (código ASCII / UTF para caractere 1). Em vez de fazer a escolha errada na metade dos casos, o VB possui funções especiais para converter caracteres em códigos ASCII / Unicode e vice-versa,
AscW
e
ChrW
respectivamente.
Expressões
46. Nada <> nulo
O literal
Nothing
no VB não significa
nulo . Significa
"o valor padrão para o tipo para o qual é usado" e acontece que, para tipos de referência, o valor padrão é nulo. A diferença só importa quando usada em um contexto em que:
- Nada assume um tipo significativo, e ...
- Não está claro pelo contexto que ele está fazendo isso.
Vejamos alguns exemplos que ilustram o que isso significa.
O primeiro, talvez um pouco estranho, mas não acho que a maioria das pessoas fique impressionada com o entendimento de que este programa imprimirá "Verdadeiro":
Module Program Sub Main() Dim i As Integer = 0 If i = Nothing Then Console.WriteLine("True") End If End Sub End Module
código fonte do githubO motivo é bem simples: você está comparando
Integer (0)
com o valor padrão de seu tipo (também 0). O problema ocorre no VB2005 / 2008 quando você adiciona tipos significativos anuláveis. Veja este exemplo:
Module Program Sub Main() Dim i = If(False, 1, Nothing) End Sub End Module
código fonte do githubEntendido, como alguém pode sugerir que o tipo
i
é um
Integer?
(
Nullable(Of Integer)
). Mas não é assim, porque
Nothing
obtém o tipo do contexto, e o único tipo nesse contexto vem do segundo operando, e este é um
non-nullable Integer
simples e
non-nullable Integer
(tecnicamente,
Nothing
nunca tem um tipo). Outra maneira de analisar esse problema é com o seguinte exemplo:
Module Program Sub Main() M(Nothing) End Sub Sub M(i As Integer) Console.WriteLine("Non-nullable") End Sub Sub M(i As Integer?) Console.WriteLine("Nullable") End Sub End Module
código fonte do githubNovamente, aqui, intuitivamente, parece que
Nothing
adiciona uma dica "anulável" e que o idioma seleciona uma sobrecarga que aceita
nullable
, mas não aceita (seleciona
non-nullable
, porque é "mais específico"). No mínimo, pode-se assumir que, como nulo em C #, a expressão
Nothing
não se aplica a
Integer
, e que a sobrecarga anulável será selecionada pelo método de exceção, mas isso se baseia novamente na ideia errada de que
Nothing = null (Is null?)
.
Nuance: Uma nova expressão
default
foi adicionada no C # 7.1 que corresponde a
Nothing
no VB. Se você reescrever todos os três exemplos acima em C # usando o
default
vez de
null
,
obtém exatamente o mesmo comportamento .
O que pode ser feito sobre isso? Existem várias sugestões, mas nenhuma ganhou ainda:
- Mostrar um aviso sempre que
Nothing
convertido em um tipo significativo e não é null
em um tipo significativo que pode ser nullable
. - Expanda lindamente
Nothing
para 0
, 0.0
, ChrW(0)
, False
, #1/1/0001 12:00:00 AM#
ChrW(0)
#1/1/0001 12:00:00 AM#
ou New T
(o valor padrão para qualquer estrutura) toda vez que seu valor em tempo de execução for um dos listados acima. - Adicione uma nova sintaxe que significa "Nulo, não, sério!", Como
Null
ou Nothing?
- Adicione uma nova sintaxe na forma de um sufixo (?) Que agrupe o valor em anulável para ajudar a deduzir o tipo, por exemplo,
If(False, 0?, Nothing)
- Adicione operadores de conversão anuláveis para tipos internos para facilitar a sugestão de inferência de tipos, por exemplo,
If (False, CInt? (0), Nothing)
Gostaria de ouvir seus pensamentos nos comentários e / ou
no Twitter .
Então, para resumir:
- Antigos tempos - VB6 e VBA têm "Nothing", "Null", "Empty" e "Missing", significando coisas diferentes.
- 2002 - no VB.NET há apenas
Nothing
(o valor padrão em um contexto específico) e em C # - somente null
. - 2005 - O C # adiciona o
default(T)
(um valor padrão do tipo T
), porque os genéricos recém-adicionados criam uma situação em que você precisa inicializar um valor, mas não sabe se é um tipo de referência ou significativo; O VB não faz nada porque esse script já está fechado por Nothing
. - 2017 - C # adiciona
default
(valor default
no contexto), pois há muitos cenários em que especificar T
redundante ou impossível
O VB continua resistindo à adição de uma expressão
Null
(ou equivalente) porque:
- A sintaxe estará quebrando as alterações.
- A sintaxe não quebrará as mudanças, mas, dependendo do contexto, significará coisas diferentes.
- A sintaxe será muito discreta (por exemplo,
Nothing?
); Imagine que você precisa falar em voz alta sobre o Nothing
e o Nothing?
para explicar algo para uma pessoa. - A sintaxe pode ser muito feia (por exemplo,
Nothing?
). - O script de expressão nula já está fechado por
Nothing
e essa função será completamente redundante na maioria das vezes. - Em todos os lugares, toda a documentação e todas as instruções devem ser atualizadas para recomendar o uso de nova sintaxe, que basicamente declara
Nothing
obsoleto na maioria dos cenários. Nothing
e Null
ainda se comportarão da mesma forma em tempo de execução com relação a ligação tardia, transformações etc.- Pode ser como uma arma em uma facada.
Algo assim.
Offtopic (mas relacionado)Aqui está um exemplo muito semelhante ao segundo acima, mas sem inferência de tipo:
Module Program Sub Main() Dim i As Integer? = If(False, 1, Nothing) Console.WriteLine(i) End Sub End Module
código fonte do githubEste programa exibe 0. Ele se comporta exatamente da mesma forma que o segundo exemplo, pelo mesmo motivo, mas ilustra um problema separado, embora relacionado. Intuitivamente, o que é
Dim i as Integer? = If(False, 1, Nothing)
Dim i as Integer? = If(False, 1, Nothing)
se comporta da mesma forma que
Dim i As Integer? : If False Then i = 1 Else i = Nothing
Dim i As Integer? : If False Then i = 1 Else i = Nothing
. Nesse caso, não é assim, porque a expressão condicional
(If)
não “passa” informações do tipo final para seus operandos. Acontece que isso divide todas as expressões no VB que dependem do que é chamado de digitação final (contextual) (
Nothing
,
AddressOf
, uma matriz de literais, expressões lambda e seqüências de caracteres interpoladas) com problemas que variam de não compilação em geral a criar discretamente valores incorretos para jogando alto exceções. Aqui está um exemplo de uma opção não compilada:
Module Program Sub Main() Dim i As Integer? = If(False, 1, Nothing) Console.WriteLine(i) Dim operation As Func(Of Integer, Integer, Integer) = If(True, AddressOf Add, AddressOf Subtract) End Sub Function Add(left As Integer, right As Integer) As Integer Return left + right End Function Function Subtract(left As Integer, right As Integer) As Integer Return left - right End Function End Module
código fonte do githubEste programa não será compilado. Em vez disso, ele relata um erro na expressão
If
que não pode determinar o tipo de expressão quando ambas as expressões
AddressOf
se destinam
AddressOf
a receber delegados
Func(Of Integer, Integer, Integer)
.
,
Nothing
null (),
Nothing
nullability
()
If(,,)
Nothing
( ) () — ,
.
47. ;
«3»:
Module Program Sub Main() Dim i As Integer = 3 M((i)) Console.WriteLine(i) End Sub Sub M(ByRef variable As Integer) variable = -variable End Sub End Module
GitHubC# «-3». , VB — ,
. ,
M(3)
,
M(i)
,
i
, . C# ( ) , M .
? VB
. Quick Basic (Copyright 1985), . ,
2002 , .
№1: « » , Visual Basic .NET.
№2: Roslyn ( ,
( ) ( )), : . C# ,
((a + b) * c a + (b * c))
. , C#, C++, , , , . : « VB?» « C#?»
source.roslyn.io —
BoundParenthesized
VB C#. , , .
48. Me
—
VB.NET
Me
. , - , — , Me Structure . Me . C#
this
,
this
.
49.
VB, , :
Class C Sub M() Extension() End Sub End Class Module Program Sub Main() End Sub <Runtime.CompilerServices.Extension> Sub Extension(c As C) End Sub End Module
GitHubC# ( something.Extension). , C#, ,
this.Extension()
.
? ,
'Me.'
, , , , . VB.NET . , .
50. (Static imports will not merge method groups)
VB « » (Java-, C# VB). ,
Imports System.Console
WriteLine()
. 2015 C# . VB Shared- ,
System.Console
System.Diagnostics.Debug
,
WriteLine
, . C# , , .
? , , VB , C# ( ). , ( , ), … , .
, VB , VB , , , , , (
#6 ). VB . , VB 2002 .
51 52. (Partial-name qualification & Smart-name resolution)
:
- , — ( ).
System
System.Windows.Forms
— , , System
System.Windows
System.Windows
System.Windows.Forms
. - , , , .
System
Windows
, Windows
Form
.
, , . . VB Imports ,
using
C# .
, VB
System
,
System
,
System
. , . ,
ExtensionAttribute
,
<Runtime.CompilerServices.Extension>
<System.Runtime.CompilerServices.Extension>
.
C# .
using System
System.Threading
Threading
.
, C# , . ,
System
,
System.Threading
Threading
. , , , , .
, , VB, C# ,
Imports
/
using
, C# using , , using .
(Quantum Namespaces) ( ), ! VB , . ,
System
ComponentModel
System.Windows.Forms
ComponentModel
?
ComponentModel
. ,
ComponentModel.PropertyChangedEventArgs
, ( , ).
System.Windows.Forms
(, , , , ), (ambiguity errors).
VB2015 (Smart Name Resolution),
System
System.Windows.Forms
ComponentModel
, ,
System.ComponentModel
System.Windows.Forms.ComponentModel
, . , , , , . , , , ..
ComponentModel.PropertyChangedEventArgs
System.ComponentModel.PropertyChangedEventArgs
,
System.Windows.Forms.ComponentModel.PropertyChangedEventArgs
. , .
,
Windows
, ( ) ( ) ( ).
WinForms/WPF
UWP
.
53. Add
#33 , VB - , . , , — , :
Class Contact Property Name As String Property FavoriteFood As String End Class Module Program Sub Main() Dim contacts = New List(Of Contact) From { {"Leo", "Chocolate"}, {"Donnie", "Bananas"}, {"Raph", "The Blood of his Enemies"}, {"Mikey", "Pizza"} } End Sub <Runtime.CompilerServices.Extension> Sub Add(collection As ICollection(Of Contact), name As String, favoriteFood As String) collection.Add(New Contact With {.Name = name, .FavoriteFood = favoriteFood}) End Sub End Module
GitHubC# , Roslyn C#, . , (
, ), VS2015.
54. ,
, VB
Dim buffer(expression) As Byte
Dim buffer = New Byte(expression) {}
expression + 1
.
Microsoft BASIC,
DIM
( dimension — ). , , , : 0 expression. Microsoft BASIC 1 ( , 1984), ( ), 2002 .
, - , , VB , BASIC C , , C, C- . ,
buffer(10)
0 10, 9!
55. VB - , C#
, . , VB ( ) , — . :
CType({1, 2, 3}, Short())
CType(New Integer() {1, 2, 3}, Short ())
, Integer
Short
.CType({1, 2, 3}, Short())
New Short() {1, 2, 3}
. .
, , VB , C#. , :
Dim empty As Integer() = {}
:
Dim array As Predicate(Of Char)() = {AddressOf Char.IsUpper, AddressOf Char.IsLower, AddressOf Char.IsWhitespace}
( ):
Dim byteOrderMark As Byte() = {&HEF, &HBB, &HBF} '
.
,
IList(Of T)
,
IReadOnlyList(Of T)
,
ICollection(Of T)
,
IReadOnlyCollection(Of T)
IEnumerable(Of T)
, , ,
ParamArray IEnumerable
.
? , VB. , . 2008 VB C# «» {}, - ( , , ). , , , + , . .
56.
, LINQ. , .
, ,
.
57. CType, DirectCast C#
/ VB C#.
VB
CType
:
- ;
- ( );
- , ,
Long
Integer
(. «»); - (unboxes) ;
- ;
- (
CTypeDynamic
).
VB
DirectCast
:
- ;
- ;
- (
Integer Byte
); - ;
- ( );
- .
C# —
(Type)expression
:
CType
C# , . , . VB C# , IL .
, C#, , . .
,
CType
, (, ).
CType
,
DirectCast
, . , , IL :
Object
(
ValueType
) CLR «unbox» VB-, , (,
Short
Integer
). , , C#. . , .
? . , , , , .
58. «»
, ,
5 Mod 2 * 3
5 VB, «» C#
5 % 2 * 3
3.
, , . , (, (\) VB), , ,
.
!59. ; + & ; + VB <> + C#
, + () & () VB + C#.
String
:VB- “1” + 1 = 2.0
- “1” & 1 = “11”
C#, + &VB- “obj: “ + AppDomain.CurrentDomain ' Error: + not defined for String and AppDomain.
- ”obj: “ & AppDomain.CurrentDomain ' Error: & not defined for String and AppDomain.
- ”obj: “ + CObj(AppDomain.CurrentDomain) ' Exception, no + operator found.
- ”obj: “ & CObj(AppDomain.CurrentDomain) ' Exception, no & operator found.
C#- «obj: » + AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
- «obj: » + (object)AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
- «obj: » + (dynamic)AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
:VBC#String Enum:VB- “Today: ” + DayOfWeek.Monday ' Exception: String «Today: » cannot be converted to Double.
- “Today: ” & DayOfWeek.Monday = “Today: 1”
- “Today: ” & DayOfWeek.Monday.ToString() = “Today: Monday”
C#- «Today: » + DayOfWeek.Monday == «Today: Monday»
: , + VB, - . + , , - . Porque Porque:
- “10” — “1” = 9.0,
- “5” * “5” = 25.0,
- “1” << “3” = 8,
- “1” + 1 = 2.0,
- “1” + “1” = “11”
. — .
: +,
. , &, , (
, ). , , .
60. : 3 / 2 = 1,5
— :
« ?» . «». :
« . ?»VB C#.
C, , ,
« 5 9?» , \. , , , , 0 ( , -
INumeric
).
61. ^ Math.Pow
Math.Pow
. , . , (
custom
) ( ,
System.Numerics.BigInteger
).
: F# **, VB F# :
op_Exponent
op_Exponentiation
. F#
Pow
. . , .
62. =/<> /
C# '==' () , , ( ). VB . VB (
Is/IsNot
) .
: - Roslyn , . . . VB , = , C# , , , .
63. =/<> ( )
VB .
-, ( ) - ( ), ,
Option Compare Binary
Option Compare Text
.
Option Compare Binary
, , VS.
( ), ,
API. :
- /: “A” = “a”/“A” <> “a”
- : “A” > “a”
Select Case: Select Case “A” : Case “a”
:
Equals: “A”.Equals(“a”)
Contains: ”A”.Contains(“a”)
Distinct: From s In {“A”, “a”} Distinct
, , : VB . ,
Option Compare
, «Empty».
Module Program Sub Main() Dim s As String = Nothing If s = "" Then Console.WriteLine("Empty") End If End Sub End Module
GitHubs = "" VB —
String.IsNullOrEmpty(s)
.
, , , , , . , , .
? Option Compare Text
, , . , , .
, , , , .
, , . , . , , (collation) SQL Server, . , VB VB6, VBA Office, Excel Access, VBScript Windows, -, -… . , , .NET API , Option Compare Text, . , .NET API, .
null, , . VB6 .
String
"". , VB
String
. VB,
Left
Mid
,
String
. null .
Len(CStr(Nothing)) = 0
Left(CStr(Nothing)
,
5) = ""
,
CStr(Nothing).Length
CStr(Nothing).Trim()
.
,
?
. ( ).
:, , , . ! VB , ,
"String A" = "String B"
,
Microsoft.VisualBasic.CompilerServices.Operators.CompareString
, - , , . LINQ- . , VB ( ). , , - , . LINQ-to-SQL, LINQ-to-Entities , Microsoft. , VB , !
, C#, VB, LINQ . : 1) , VB , , 2) , VB , , LINQ-. , VB ().
: , « API».
Option Compare
VB,
InStr.Replace
Microsoft.VisualBasic.Strings
. , ?
, , , ? , , , : , , .
64. Nullable ( null )
VB C# - nullable. , (null-propagation).
SQL, , , null. , (, +), null, null.
"?."
:
obj?.Property obj
null, null, .
nullable , VB, C# . - : .
VB, nullable , null, null . 1 + null null null + null null. , (, = <>) C#:
- VB,
Is/IsNot
, Boolean?
- C# (==, !=, >, <, >=, <=)
bool
bool?
VB ( nullable ) null
null .
Boolean
=
Boolean?
,
True
,
False
null
.
. C#
non-nullable bool
,
.
,
. null. VB
NULL =
NULL —
NULL , TRUE.
, :

.
Null , , , C# .
. C# VB,
« null?» C#
(if (value == null))
. VB , VB (=/<>)
(Is/IsNot)
, VB
Is Nothing
non-nullable Boolean
.
, VB null, null.
And/AndAlso
Or/OrElse
.
Integer?
( ), VB, C# null, :
- 1 AND NULL NULL
- 1 OR NULL NULL
Boolean?
, VB .
- FALSE AND NULL FALSE
- TRUE OR NULL TRUE
- TRUE AND NULL NULL
- FALSE OR NULL NULL
,
True/False
, , null. ,
AndAlso
OrElse
.
C# (&&/||) (&/|)
nullable boolean (bool?)
. , , non-nullable boolean nullable boolean .
?VB , - :
Imports System.ComponentModel Class BindableRange Implements INotifyPropertyChanged Property _EndDate As Date? Property EndDate As Date? Get Return _EndDate End Get Set(value As Date?)
GitHub, , , , «EndDate change» . , ,
VB null ? ,
EndDate
, , ,
Nothing
.
VB :
«, , . » :
If value <> _EndDate Then _EndDate = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(EndDate))) End If
! . ,
non-nullable . ,
. , :
If value Is Nothing AndAlso _EndDate Is Nothing Then Return If value <> _EndDate Then Return
?, C# , VB. ( nullable , ), , null.
null —
«» « » . .
null « » «» . , , : comparer, , comparer . Roslyn,
Optional(Of T)
, , , null, , .
, NULL « », VB :
- , « , ?» « ».
- : « , ?» « ».
, ,
SQL- . , NULL SQL , NULL. . , , NULL . , . , , ( ). , , , , , NULL , SQL ( ).
VB.
nullable 2008 , VB ?LINQ to SQL
VB , , , , , , LINQ- . !
. SQL Server, ,
SET ANSI_NULLS OFF , SQL- C#,
WHERE Column = NULL
. , , OFF ( ). SQL Server ( ) . :
« ? . , - Option ANSI_NULLS Off VB.NET?» . :

, , , , , SQL Server, VB.
Algo assim.
65. 1:1
, VB , , , . VB - , .
, , , , . VB , , , , , VB .
9.8.4 .
66. Function() a = b () => a = b
. ,
() => expression
C#
Function() expression
VB.
Function()
-, - , VB.
a = b
,
a
b
(
Boolean
),
b
. - (delegate relaxation) VB ( -) Sub- ( ). .
() => a = b
C# VB —
Sub() a = b
. — -
, .
=, , . (
Sub
-) , (
Function
-) .
67. Async Function
async void
C#
async
-, , ,
Task
void
, ,
Task
, .
VB.NET , ..
void Async
Async Sub
,
Task
Task(Of T)
—
Async Function
. , , VB, (relaxing)
Task Async
void
.
Async Sub
, , .
68. () VB
, VB:
Class Foo
GitHubVB,
C#. -,
Foo
Select
, ,
Where
.
Select
, ,
Select
,
Integer
. C# ,
.Where
(
Select
). , , .
LINQ API. , VB C#, . , C# , « », , , , . - , «» , , -.
, VB
, , C# , .
, Roslyn, :
« (range variables)?» « ?» . . , VB ,
Let
, C# — . , VB, C# 2012 , :
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CSharpExamples { struct Point { public int X { get { return 0; } } public int Y { get { return 0; } } } class Foo { public IEnumerable<Point> Select<T>(Func<string, T> selector) { return new Point[0]; } } static class Program { static void Main(string[] args) { var c = new Foo(); var q = from X in c let Y = "" select Y.CompareTo(-1); } } }
GitHub, — ? X, —
string
.
let
Y
, string. , Point,
X
Y
, ,
int
X
Y
, «» .
Y
select
,
int
int
`, … .
,
« ?» . VS2015 C# , «». , Roslyn C#, . , ( , ), - .
? , , , . , , VB C# .
69 70. As
From
cast
; 'As'
( , …)
From x As Integer In y
VB, ,
from int x in y
C#.
-, C# , ( ) .
.Cast<T>()
. VB , , , , .
-, ,
.Cast
( ). , , ,
.Cast
.Select
.
? . VB . ,
For Each x As T In collection
,
As T
.
From
As
For Each
( ,
As
).
71-75. Select
, ,
Por exemplo:
From x In y Where x > 10
. , Select
.From x In y Select x Where x > 10
.From x In y Select x
, From x In y Select x = x
, x
— x
, x
— Select
. Select
.From x In y Select z = x.ToString()
, x
.From x In y Select x.FirstName
, From x In y Select FirstName = x.FirstName
.From x In y Select x.FirstName, x.LastName
— From x In y Select New With {x.FirstName, y.LastName}
, , . IEnumerable(Of $AnonymousType$)
, .
? (
Amanda Silver ). !
- ,
Select
, SQL , Select
, . LINQ VB Select , SQL, From . - , , .
- ,
Select
, SQL, - - . VB comma separated ( ) -. - ,
Select
, , , , , , , — .
? , , - , , :
Module Program Sub Main() Dim numbers = {1, 2, 3}
GitHubBC36606: Range variable name cannot match the name of a member of the 'Object' class
BC30978: Range variable '…' hides a variable in an enclosing block or a range variable previously defined in the query expression
— ,
Object
, , , , . (
n.ToString()
), . , .
76+.
. … … . … 20-25 (
— .. ).
Minuto de publicidade. 15-16 - .NET- DotNext 2019 Piter . , . , . .