在本文的
第一部分中,有关TIOBE等级的VB.NET优于C#的话题在评论中引起了热烈的反响。 因此,根据
AngReload的
建议 ,让我们看一下StackOverflow的
趋势 。

C#仍然很强大! 上次讨论这么长时间的革命被取消了! 同志们,万岁! 还是不行 TIOBE等级基于搜索引擎查询,而SO等级则基于所问问题的标签。 也许包括很多没有专业知识的人在内的VB.NET开发人员根本不知道StackOverflow的存在? 或是通过Google甚至Bing到达那里,都不知道如何提出问题? 或者,也许他们有足够的Miscrosoft文档,而所有几个问题都已得到解答。
无论如何,VB.NET的份额都是引人注目且稳定的,尽管在数量上并不是第一位。 当然,如果没有强大的设计师和语言开发人员团队,这样的结果将是不可能的。 以下是该团队成员
Anthony Green的文章翻译的第二部分。
目录内容
转换次数
34.布尔变换
将
Boolean True
转换为任何带符号的数字类型将产生
-1
,而将其转换为任何无符号的类型将为该类型提供最大值,而在C#中没有此类转换。 但是,例如,
Convert.ToInt32
方法会将
True
转换为
1
,这就是
IL
最常表示的方式。 在相反的方向上,除
0
以外的任何数字都将转换为
True
。
怎么了 VB倾向于使用
-1
到
1
的原因是因为在任何语言中0(所有位都设置为0)的按位取反是
-1
(所有位都设置为
1
),因此使用此值将逻辑和按位组合
And
,
Or
和
Xor
等运算。
还支持与“ True”和“ False”行之间的转换(当然,不区分大小写)。
35.即使Option Strict设置为On,Enum类型之间以及Enum类型与其基本类型之间的转换也是完全不受限制的
从哲学的角度来看,语言是指
Enum
类型,而不是基本整数类型的一组命名常量。 最明显的地方是平等。 始终允许将任何整数与枚举值进行比较,而在C#中会产生错误。
故事时间: Roslyn API经历了许多内部修订。 但是在每种语言中,都为每种语言分配了
SyntaxKind
枚举,该枚举告诉您节点表示什么语法(例如
IfStatement
,
TryCastExpression
)。 有一次,开发人员使用了一个试图从该语言中抽象出来的API并返回了一个
SyntaxKind
值,但仅作为
Integer
,并且在比较原始
Integer
和
SyntaxKind
时没有收到错误,该开发人员立即来到我的办公室并抱怨:
“ int is实施细节,我应该被迫做演员!” 。
多年来,在API的下一个修订版中,我们完全删除了指向特定于语言的类型的属性(
Property Kind As SyntaxKind
),并且所有API开始返回
Integer
。 所有的C#代码都中断了,所有的VB代码继续工作,好像什么都没发生。
稍后,我们决定将该属性重命名为
RawKind
并添加特定于语言的扩展方法
Kind()
。 所有C#代码都中断了,因为调用方法需要使用括号,但是由于VB中不需要括号,因此所有VB代码都继续工作,就好像什么都没发生一样。
36.检查整数运算的溢出/负溢出完全由编译环境(项目设置)控制,但是VB和C#使用不同的默认值。 在VB中,默认情况下启用了溢出检查
整数类型具有范围,例如,
Byte
可以表示0到255之间的值。那么,将
Byte
1与
Byte
255相加会发生什么? 如果禁用了上溢/下溢检查,则值滚动到0。如果类型是带符号的,则滚动到最低的负数(例如,-128表示
SByte
)。 这很可能表明程序中存在错误。 如果启用了上溢/下溢检查,则会引发异常。 要理解我的意思,请看一下这个无害的
For
循环。
Module Program Sub Main() For i As Byte = 0 To 255 Console.WriteLine(i) Next End Sub End Module
github源代码默认情况下,此循环将在VB中引发异常(因为循环的最后一次迭代超出了
Byte
边界。但是,关闭了溢出检查后,由于255之后我又变为0,所以它将循环。
当类型的最小值减去以下的最小值得到最大值时,下溢是相反的情况。
一个更常见的溢出情况就是两个数字的加法。 将数字130和150都作为
Byte
。 如果将它们放在一起,答案是280,它不适合Byte。 但是您的处理器无法感知到这一点。 相反,他报告答案是24。
顺便说一下,这与转换无关。 两个字节相加得到一个字节; 这只是二进制数学的工作方式。 尽管例如通过尝试将Long转换为Integer时,也可以通过执行转换来溢出。 在不检查溢出的情况下,该程序只截取了多余的位和填充到该变量中的内容。
有什么区别? 性能。 像所有其他安全检查一样,与非检查选项相比,检查CLR是否溢出需要更多的计算时间。 VB基于这样的理念,即开发人员的生产力比计算性能更重要,因此默认情况下您启用了安全检查。
今天的C#开发团队
可能对项目的默认设置做出不同的决定,但是考虑到最初的C#开发人员来自C / C ++开发人员,因此这群人可能会要求代码不做任何事情,这可能会浪费处理器周期;
这是一个困难的哲学差异 。
注意:即使关闭了上溢/下溢检查,从
Single
或
Double
的
PositiveInfinity
,
NegativeInfinity
,
NaN
到
Decimal
引发异常,因为原则上这些值都不能用Decimal表示。
37.将浮点数转换为整数类型使用银行取整而不是截断
如果在VB中将1.7转换为整数,结果将为2。在C#中,结果将为1。关于美国以外的数学规则,我什么也没说,但是当我从实数转换为整数时,我本能地舍入。 在程序员圈子之外,我所认识的人都不相信1.7的最接近整数是1。
实际上有几种舍入方法,VB(以及Math.Round方法)中使用的舍入类型默认称为库舍入或四舍五入统计量。 其本质是,对于两个整数之间的中间数字,VB会四舍五入到最接近的偶数。 因此1.5会四舍五入为2,4.5会四舍五入为4。这实际上对我们在学校的授课方式不起作用-我被教导从0.5向上舍入(从技术上讲,从零开始舍入到边)。 但是,顾名思义,银行四舍五入的优势在于,通过大量计算,您可以在四舍五入时进行除法运算,而不必总是付出或总是保留金钱。 换句话说,在较大的数据集上,这将数据失真限制为最终的统计偏差。
差异来自何处? 四舍五入更加直观和实用,截断速度更快。 如果考虑在LOB应用程序中使用VB,尤其是在VBA上运行的Excel宏之类的应用程序中使用VB,则简单地舍弃小数位会导致...问题。
我认为很明显,转换方法始终是一个有争议的问题,应明确指出,但是如果您需要选择一个...
38.将NotInheritable类与在编译时未实现的接口相互转换不是错误的
一般来说,如果您正在检查NonInheritable类的接口实现,则可以在编译时理解是否可以进行这种转换,因为您知道此类型的所有接口及其所有基本类型。 如果类型是继承的,则无法确定是否无法进行这种转换,因为所引用的运行时对象的类型实际上可能具有实现该接口的更多派生类型。 但是,由于COM互操作而有一个例外,当在编译时可能看不到该类型与接口有关,但在运行时它将与接口有关。 因此,在这种情况下,VB编译器会生成警告。
怎么了 VB和COM在旧社区里还是个孩子的时候就一起成长。 因此,在语言设计中有几种解决方案,其中VB高度关注仅在.NET 1.0发行时COM中才存在的问题。
39.尝试将null解包(拆箱)为有意义的类型会导致该类型的默认值,而不是NullReferenceException
我认为从技术上讲,引用类型也是如此,但是可以:
CInt(CObj(Nothing)) = 0
怎么了 因为
CInt(Nothing) = 0
,并且语言趋于一致,而不管您是否键入变量。 这适用于任何结构,而不仅仅是内置的有意义的类型。 有关更多详细信息,请参见
#25的
基本原理 。
40.拆箱支持原始类型转换
在VB和C#中,都可以将
Short
转换为
Integer
,但是如果尝试将压缩的
Short
转换为
Integer
怎么办? 在VB中,
Short
将首先解压缩,然后转换为
Integer
。 在C#中,除非您在转换为
int
之前手动解压缩short,否则将抛出
InvalidCastException
。
这适用于所有内部转换,即打包的数字类型,字符串和数字类型之间的转换,字符串和日期(是,小数和日期是原始类型)。
怎么了 同样,为确保行为一致,无论您的程序是完全键入,键入为Object还是从一个选项重构到另一个选项。 请参阅上面的
#39 。
41.在String
和Char
之间进行转换
String
转换为Char
,表示其第一个字符。Char
以唯一合理的方式转换为String
。
因为除了我之外,没有人记得VB中字符文字的语法(而且不应该)。
42.在String
和Char
数组之间有转换
String
转换为由其所有Char
组成的Char
数组。Char
数组将转换为包含其所有元素的String
。
为了明确起见:这些转换会创建新对象,您无法访问内部
String
结构。
有趣的故事:我曾经发现(或者可能正在报告它,并且我正在研究)打破.NET 3.5和4.0之间的更改,因为.NET团队在这些版本之间将
ParamArray
修饰符添加到第二个
String.Join
重载
String.Join
(该
String.Join
需要一个字符串数组) 。 确切的假设会随着时间的流逝而丢失(可能会更好),但是,正如我所相信的,原因是,通过
ParamArray
修饰符,您现在可以将
Char
数组转换为字符串,并将其作为单独的元素传递给参数数组。 有趣的主题。
43和44。从字符串到数字和日期类型的转换支持文字语法(通常)
CInt("&HFF") = 255
CInt("1e6") = 1_000_000
CDate("#12/31/1999#") = #12/31/1999#
这可以与基本前缀一起使用,并可以使用非常方便的方式将十六进制(或八进制)输入转换为数字:
CInt("&H" & input)
。 不幸的是,由于VB运行时尚未更新为支持二进制前缀&B或
1_000
位数字组
1_000
,因此这种对称性在撰写本文时有所
1_000
,但我希望在下一版本中可以解决此问题。 科学符号有效,但没有类型后缀,日期转换也支持标准日期格式,因此ISO-8601中使用的JSON格式也适用:
CDate("2012-03-19T07: 22Z") = #3/19/2012 02:22:00 AM#
。
怎么了 除了方便我没有其他原因。 但是我
真的很想为当今网络中几乎无处不在的其他常见格式提供支持,例如#FF,U + FF,0xFF。 我认为这可以极大地简化某些类型应用程序中的生活...
45. Char
和整数类型之间没有NO转换
什么?!?!?阅读完所有这些其他转换后,您感到惊讶吗? VB禁止在
Char
和
Integer
之间进行转换:
CInt("A"c)
无法编译。CChar(1)
无法编译。
怎么了 目前尚不清楚会发生什么。 通常,在这种情况下,VB使用务实和/或直观的方法,但是对于表达式
CInt("1")
我认为一半读者希望数字1(字符值1),而一半读者希望数字49(ASCII / UTF代码用于字符1)。 VB并没有在一半的情况下做出错误的选择,而是具有特殊的功能,可以将字符转换为ASCII / Unicode代码,反之亦然
ChrW
分别是
AscW
和
ChrW
。
表达方式
46.什么都不是<> null
VB中的文字
Nothing
并不表示
null 。 它的意思是
“它所使用的类型的默认值”,并且碰巧对于引用类型来说,默认值为null。 仅当在以下情况下使用时,差异才重要:
- 没有什么是重要的类型,而且...
- 从上下文中还不清楚他正在这样做。
让我们看几个例子,说明这意味着什么。
首先,也许有些奇怪,但是我认为大多数人不会因为该程序将显示“ True”而被炸毁:
Module Program Sub Main() Dim i As Integer = 0 If i = Nothing Then Console.WriteLine("True") End If End Sub End Module
github源代码原因很简单:您正在将
Integer (0)
与该类型的默认值(也为0)进行比较。 当您添加可为空的有意义的类型时,会在VB2005 / 2008中发生此问题。 看一下这个例子:
Module Program Sub Main() Dim i = If(False, 1, Nothing) End Sub End Module
github源代码明白了,有人怎么会建议类型
i
是
Integer?
(
Nullable(Of Integer)
)。 但是事实并非如此,因为
Nothing
从上下文中获取类型,并且该上下文中的唯一类型来自第二个操作数,并且这是一个简单的
non-nullable Integer
(从技术上讲,
Nothing
从不具有类型)。 下面的示例是解决此问题的另一种方法:
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
github源代码再次,在这里,从直觉上看,似乎
Nothing
也
Nothing
添加“可空”提示,并且语言选择了接受
nullable
的重载,但它不接受(选择
non-nullable
,因为它是“最具体的”)。 至少可以假定,像C#中的null一样,
Nothing
表达式根本不适用于
Integer
,并且可以通过异常方法选择可为null的重载,但这再次基于错误的想法,即
Nothing = null (Is null?)
。
注意:在C#7.1中添加了一个新的
default
表达式,该表达式与VB中的
Nothing
不匹配。 如果使用
default
而不是
null
在C#中重写以上所有三个示例,
则将获得完全相同的行为 。
该怎么办? 有几个建议,但没有一个能胜任:
- 每次显示警告时,
Nothing
转换为有意义的类型,并且在nullable
为nullable
有效类型中不为null
。 - 精美地将
Nothing
扩展为ChrW(0)
, ChrW(0)
, False
, #1/1/0001 12:00:00 AM#
ChrW(0)
#1/1/0001 12:00:00 AM#
或New T
(任何结构的默认值)每次在运行时的值是以下之一时上面列出。 - 添加一个新语法,意思是“ Null,不,真的!”就像
Null
还是Nothing?
- 添加后缀(?)形式的新语法,该语法将值包装为可空值以帮助推断类型,例如
If(False, 0?, Nothing)
- 为内置类型添加可为空的转换运算符,以使其更容易给出类型推断的提示,例如,
If (False, CInt? (0), Nothing)
我想在评论中和/或
在Twitter上听到您的想法。
总结一下:
- 以前-VB6和VBA的含义为“ Nothing”,“ Null”,“ Empty”和“ Missing”。
- 2002-在VB.NET中只有
Nothing
(特定上下文中的默认值),而在C#中则只有null
。 - 2005年-C#添加了
default(T)
(类型T
的默认值),因为新添加的泛型会导致您需要初始化值,但是您不知道该值是引用类型还是有效值; VB不执行任何操作,因为Nothing
已关闭该脚本。 - 2017年-C#添加了
default
值(上下文中的default
值),因为在许多情况下指定T
冗余或不可能
VB继续拒绝添加
Null
表达式(或等效表达式),因为:
- 语法将带来重大变化。
- 语法不会发生重大变化,但是取决于上下文,其含义将有所不同。
- 语法不会太显眼(例如
Nothing?
); 想象一下,您需要大声谈论Nothing
, Nothing?
向某人解释一些事情。 - 语法可能太丑陋(例如
Nothing?
)。 Nothing
已关闭了空表达式脚本,并且该功能在大多数情况下是完全多余的。- 在任何地方,所有文档和所有说明均应进行更新,以建议使用新语法,该语法在大多数情况下基本上都声明
Nothing
。 - 在后期绑定,转换等方面,
Nothing
和Null
在运行时的行为仍然相同。 - 就像刺中的枪一样。
这样的东西。
离题(但相关)这是一个非常类似于上面第二个示例的示例,但是没有类型推断:
Module Program Sub Main() Dim i As Integer? = If(False, 1, Nothing) Console.WriteLine(i) End Sub End Module
github源代码该程序显示为0。出于相同的原因,它的行为与第二个示例完全相同,但说明了一个单独的尽管相关的问题。 直观地,
Dim i as Integer? = If(False, 1, Nothing)
Dim i as Integer? = If(False, 1, Nothing)
行为与
Dim i As Integer? : If False Then i = 1 Else i = Nothing
相同
Dim i As Integer? : If False Then i = 1 Else i = Nothing
Dim i As Integer? : If False Then i = 1 Else i = Nothing
。 在这种情况下,情况并非如此,因为条件表达式
(If)
不会将最终类型的信息“传递”到其操作数。 事实证明,这会破坏VB中依赖于最终(上下文)类型的所有表达式(
Nothing
,
AddressOf
,文字,lambda表达式和内插字符串的数组),问题的范围通常从反编译到静默创建不正确的值,再到大声地抛出异常。 这是未编译选项的示例:
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
github源代码该程序将无法编译。 相反,它在
If
表达式中报告一个错误,当两个
AddressOf
表达式都
AddressOf
打算接收
Func(Of Integer, Integer, Integer)
委托
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, - . + , , - . 怎么了 :
- “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.
这样的东西。
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
, ,
例如:
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 (
— .. ).
分钟的广告。 15-16 - .NET- DotNext 2019 Piter . , . , . .