VB.NET和C#之间的差异的详尽列表。 第二部分

在本文的第一部分中,有关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倾向于使用-11的原因是因为在任何语言中0(所有位都设置为0)的按位取反是-1 (所有位都设置为1 ),因此使用此值将逻辑和按位组合AndOrXor等运算。
还支持与“ True”和“ False”行之间的转换(当然,不区分大小写)。

35.即使Option Strict设置为On,Enum类型之间以及Enum类型与其基本类型之间的转换也是完全不受限制的


从哲学的角度来看,语言是指Enum类型,而不是基本整数类型的一组命名常量。 最明显的地方是平等。 始终允许将任何整数与枚举值进行比较,而在C#中会产生错误。

故事时间: Roslyn API经历了许多内部修订。 但是在每种语言中,都为每种语言分配了SyntaxKind枚举,该枚举告诉您节点表示什么语法(例如IfStatementTryCastExpression )。 有一次,开发人员使用了一个试图从该语言中抽象出来的API并返回了一个SyntaxKind值,但仅作为Integer ,并且在比较原始IntegerSyntaxKind时没有收到错误,该开发人员立即来到我的办公室并抱怨: “ 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 ++开发人员,因此这群人可能会要求代码不做任何事情,这可能会浪费处理器周期; 这是一个困难的哲学差异

注意:即使关闭了上溢/下溢检查,从SingleDoublePositiveInfinityNegativeInfinityNaNDecimal引发异常,因为原则上这些值都不能用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.在StringChar之间进行转换


  • String转换为Char ,表示其第一个字符。
  • Char以唯一合理的方式转换为String

因为除了我之外,没有人记得VB中字符文字的语法(而且不应该)。

42.在StringChar数组之间有转换


  • 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禁止在CharInteger之间进行转换:

  • CInt("A"c)无法编译。
  • CChar(1)无法编译。

怎么了 目前尚不清楚会发生什么。 通常,在这种情况下,VB使用务实和/或直观的方法,但是对于表达式CInt("1")我认为一半读者希望数字1(字符值1),而一半读者希望数字49(ASCII / UTF代码用于字符1)。 VB并没有在一半的情况下做出错误的选择,而是具有特殊的功能,可以将字符转换为ASCII / Unicode代码,反之亦然ChrW分别是AscWChrW

表达方式


46.什么都不是<> null


VB中的文字Nothing并不表示null 。 它的意思是“它所使用的类型的默认值”,并且碰巧对于引用类型来说,默认值为null。 仅当在以下情况下使用时,差异才重要:

  1. 没有什么是重要的类型,而且...
  2. 从上下文中还不清楚他正在这样做。

让我们看几个例子,说明这意味着什么。

首先,也许有些奇怪,但是我认为大多数人不会因为该程序将显示“ 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源代码

明白了,有人怎么会建议类型iInteger?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源代码

再次,在这里,从直觉上看,似乎NothingNothing添加“可空”提示,并且语言选择了接受nullable的重载,但它不接受(选择non-nullable ,因为它是“最具体的”)。 至少可以假定,像C#中的null一样, Nothing表达式根本不适用于Integer ,并且可以通过异常方法选择可为null的重载,但这再次基于错误的想法,即Nothing = null (Is null?)

注意:在C#7.1中添加了一个新的default表达式,该表达式与VB中的Nothing不匹配。 如果使用default而不是null在C#中重写以上所有三个示例, 则将获得完全相同的行为

该怎么办? 有几个建议,但没有一个能胜任:

  • 每次显示警告时, Nothing转换为有意义的类型,并且在nullablenullable有效类型中不为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? ); 想象一下,您需要大声谈论NothingNothing? 向某人解释一些事情。
  • 语法可能太丑陋(例如Nothing? )。
  • Nothing已关闭了空表达式脚本,并且该功能在大多数情况下是完全多余的。
  • 在任何地方,所有文档和所有说明均应进行更新,以建议使用新语法,该语法在大多数情况下基本上都声明Nothing
  • 在后期绑定,转换等方面, NothingNull在运行时的行为仍然相同。
  • 就像刺中的枪一样。

这样的东西。

离题(但相关)

这是一个非常类似于上面第二个示例的示例,但是没有类型推断:

 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中依赖于最终(上下文)类型的所有表达式( NothingAddressOf ,文字,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 

GitHub

C# «-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.ioBoundParenthesized 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 

GitHub

C# ( 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 

GitHub

C# , 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#

  • «1» + 1 == «11»

, + &
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()

:
VB

  • 1 + 1 = 2
  • 1 & 1 = “11”

C#

  • 1 + 1 == 2

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 

GitHub

s = "" 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 = NULLNULL , 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?) ' This line here: If value = _EndDate Then Return _EndDate = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(EndDate))) End Set End Property Public Event PropertyChanged As PropertyChangedEventHandler _ Implements INotifyPropertyChanged.PropertyChanged End Class Module Program WithEvents Range As New BindableRange Sub Main() Range.EndDate = Today Range.EndDate = Today Range.EndDate = Nothing Range.EndDate = Nothing End Sub Private Sub BindableRange_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _ Handles Range.PropertyChanged Console.WriteLine(e.PropertyName & " changed.") End Sub End Module 

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 'Function [Select](Of T)(selector As Func(Of String, T)) As Foo ' Return Me 'End Function Function Where(predicate As Func(Of String, Boolean)) As Integer Return 0 End Function End Class Module Program Sub Main() Dim c As New Foo Dim q = From x In c Where True Select x End Sub End Module 

GitHub

VB, 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 , xx , xSelect . 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.LastNameFrom 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} ' BC36606: Range variable name cannot match the name of a member of the 'Object' class. Dim q = From n In numbers Select n.ToString() End Sub End Module 

GitHub

BC36606: 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 . , . , . .

Source: https://habr.com/ru/post/zh-CN445580/


All Articles