VB.NET 的隐藏特性 VB.NET? ?

通过浏览隐藏特性,我学到了很多东西 当我找不到东西的时候,我很惊讶 类似于 VB.NET。

那么,它的一些隐藏或鲜为人知的特征是什么呢?

29481 次浏览
  • AndAlso/OrElse 逻辑运算符

(编辑: 在这里了解更多: 我应该总是使用 AndAnd 和 OrElse 运算符吗?)

我一直使用的一个主要节省时间的关键字是 :

With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With

我只是不喜欢多打字!

我不知道你怎么称呼它隐藏,但 If操作员可以计数。

在某种程度上,它与许多类 C 语言中的 ?:(三进制)或 ??操作符非常相似。但是,需要注意的是,它确实计算了所有参数,因此不要传入任何可能导致异常(除非您希望这样做)或任何可能导致意外副作用的内容。

用法:

Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
  • 子命名空间在导入其父命名空间后处于作用域中。例如,不必导入 System.IO 或者说 System.IO.File 来使用 File 类,只需说 IO.File 即可。这是一个简单的例子: 在有些地方,这个特性真的很方便,而 C # 并没有这样做。

If条件运算符和合并运算符

I don't know how hidden you'd call it, but the Iif([expression],[value if true],[value if false]) As Object function could count.

它不像 不赞成那么隐蔽!VB 9中的 If操作符要好得多,它与 C # 的条件运算符和合并运算符完全一样(取决于你想要什么) :

Dim x = If(a = b, c, d)


Dim hello As String = Nothing
Dim y = If(hello, "World")

为了展示另一个例子:

This will work with If(), but cause an exception with IIf()

Dim x = If(b<>0,a/b,0)

Exception When子句在很大程度上是未知的。

想想这个:

Public Sub Login(host as string, user as String, password as string, _
Optional bRetry as Boolean = False)
Try
ssh.Connect(host, user, password)
Catch ex as TimeoutException When Not bRetry
''//Try again, but only once.
Login(host, user, password, True)
Catch ex as TimeoutException
''//Log exception
End Try
End Sub

对象初始化也在里面!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

我过去非常喜欢可选的函数参数,但是现在我很少使用它们了,因为我必须在 C # 和 VB 之间来回走动很多次。C # 什么时候支持它们?C + + 甚至 C 都有(某种程度上) !

进口别名也基本上不为人知:

Import winf = System.Windows.Forms


''Later
Dim x as winf.Form

定制 Enum

One of the real 藏起来了 features of VB is the completionlist XML documentation tag that can be used to create own Enum-like types with extended functionality. This feature doesn't work in C#, though.

我最近的一个代码中的一个例子:

'
''' <completionlist cref="RuleTemplates"/>
Public Class Rule
Private ReadOnly m_Expression As String
Private ReadOnly m_Options As RegexOptions


Public Sub New(ByVal expression As String)
Me.New(expression, RegexOptions.None)
End Sub


Public Sub New(ByVal expression As String, ByVal options As RegexOptions)
m_Expression = expression
m_options = options
End Sub


Public ReadOnly Property Expression() As String
Get
Return m_Expression
End Get
End Property


Public ReadOnly Property Options() As RegexOptions
Get
Return m_Options
End Get
End Property
End Class


Public NotInheritable Class RuleTemplates
Public Shared ReadOnly Whitespace As New Rule("\s+")
Public Shared ReadOnly Identifier As New Rule("\w+")
Public Shared ReadOnly [String] As New Rule("""([^""]|"""")*""")
End Class

现在,当为声明为 Rule的变量赋值时,IDE 提供了一个来自 RuleTemplates的可能值的 IntelliSense 列表。

编辑:

因为这是一个依赖于 IDE 的特性,所以当你使用它的时候很难显示它的外观,但是我只用一个截图:

行动 http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png 的完成清单

实际上,IntelliSense 与使用 Enum时得到的结果是100% 相同的。

The Using statement is new as of VB 8, C# had it from the start. It calls dispose automagically for you.

例如。

Using lockThis as New MyLocker(objToLock)


End Using

别名空间

Imports Lan = Langauge

虽然不是 VB.Net 独有的,但是当遇到名称空间冲突时,它常常被遗忘。

同样重要的是要记住,在默认情况下,VB.NET 项目有一个根命名空间,它是项目属性的一部分。默认情况下,此根命名空间的名称与项目相同。在使用命名空间块结构时,Name 实际上被追加到根命名空间。例如: 如果项目名为 MyProject,那么我们可以将一个变量声明为:

Private obj As MyProject.MyNamespace.MyClass

若要更改根命名空间,请使用 Project-> Properties 菜单选项。也可以清除根命名空间,这意味着所有命名空间块都成为它们包含的代码的根级别。

这是内置的,而且比 C # 有明显的优势。实现接口 Method 而不必使用相同名称的能力。

Such as:

Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo


End Sub

别忘了 XML Literals

Dim contact2 = _
<contact>
<name>Patrick Hines</name>
<%= From p In phoneNumbers2 _
Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
%>
</contact>

Typedefs

VB 通过 Import别名知道一种基本的 typedef:

Imports S = System.String


Dim x As S = "Hello"

这在与泛型类型一起使用时更有用:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)

你可以使用 REM 来注释掉一行而不是’ . Not super useful, but helps important comments standout w/o using "!!!!!!!" or whatever.

如果您需要一个变量名来匹配关键字的名称,请用括号将其括起来。不是尼克。尽管这是最好的做法,但它可以被明智地使用。

例如:。

Class CodeException
Public [Error] as String
''...
End Class


''later
Dim e as new CodeException
e.Error = "Invalid Syntax"

例如来自评论的例子(@Pondidium) :

Class Timer
Public Sub Start()
''...
End Sub


Public Sub [Stop]()
''...
End Sub

Title Case in VB.Net can be achieved by an old VB6 fxn:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID

DirectCast

DirectCast是个奇迹。表面上,它的工作原理类似于 CType操作符,因为它将对象从一种类型转换为另一种类型。然而,它的工作原理是一套更为严格的规则。因此,CType的实际行为通常是不透明的,而且根本不清楚执行哪种类型的转换。

DirectCast只支持两种不同的操作:

  • Unboxing of a value type, and
  • 在类层次结构中上升。

任何其他强制转换都不会起作用(例如,尝试将 Integer解压到 Double) ,并将导致编译时/运行时错误(取决于情况和静态类型检查可以检测到的内容)。因此,只要有可能,我就使用 DirectCast,因为它最能抓住我的意图: 根据具体情况,我要么解压缩已知类型的值,要么执行向上转换。就这样。

另一方面,使用 CType使代码读者不知道程序员真正的意图是什么,因为它解析了各种不同的操作,包括调用用户定义的代码。

为什么这是一个隐藏的特征?VB 团队发布了一个指南 1,该指南不鼓励使用 DirectCast(尽管它实际上更快!)为了使代码更加统一。我认为这是一个错误的指导方针,应该被颠倒过来: Whenever possible, favour ABC0 over the more general CType operator.它使代码更加清晰。另一方面,只有在确实需要调用 CType的情况下才应该调用 CType,也就是说,应该调用一个收缩的 CType操作符(参考 运算符重载)。


1) 我无法找到指南的链接,但我找到了 Paul Vick 接手了(VB 团队的首席开发员) :

In the real world, you're hardly ever going to notice the difference, so you might as well go with the more flexible conversion operators like CType, CInt, etc.


(编辑: Zack: 在这里了解更多: 我应该如何在 VB.NET 中进行转换?)

请考虑以下事件声明

Public Event SomethingHappened As EventHandler

在 C # 中,可以使用以下语法检查事件订阅者:

if(SomethingHappened != null)
{
...
}

但是,VB.NET 编译器不支持这一点。它实际上创建了一个隐藏的私有成员字段,这在 IntelliSense 中是不可见的:

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If

更多信息:

Http://jelle.druyts.net/2003/05/09/behindthescenesofeventsinvbnet.aspx Http://blogs.msdn.com/vbteam/archive/2009/09/25/testing-events-for-nothing-null-doug-rothaus.aspx

自订活动

虽然很少有用,但事件处理可以进行大量定制:

Public Class ApplePie
Private ReadOnly m_BakedEvent As New List(Of EventHandler)()


Custom Event Baked As EventHandler
AddHandler(ByVal value As EventHandler)
Console.WriteLine("Adding a new subscriber: {0}", value.Method)
m_BakedEvent.Add(value)
End AddHandler


RemoveHandler(ByVal value As EventHandler)
Console.WriteLine("Removing subscriber: {0}", value.Method)
m_BakedEvent.Remove(value)
End RemoveHandler


RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("{0} is raising an event.", sender)
For Each ev In m_BakedEvent
ev.Invoke(sender, e)
Next
End RaiseEvent
End Event


Public Sub Bake()
''// 1. Add ingredients
''// 2. Stir
''// 3. Put into oven (heated, not pre-heated!)
''// 4. Bake
RaiseEvent Baked(Me, EventArgs.Empty)
''// 5. Digest
End Sub
End Class

然后可以以下列方式测试这一点:

Module Module1
Public Sub Foo(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("Hmm, freshly baked apple pie.")
End Sub


Sub Main()
Dim pie As New ApplePie()
AddHandler pie.Baked, AddressOf Foo
pie.Bake()
RemoveHandler pie.Baked, AddressOf Foo
End Sub
End Module

方法中的静态成员。

例如:

Function CleanString(byval input As String) As String
Static pattern As New RegEx("...")


return pattern.Replace(input, "")
End Function

在上面的函数中,无论调用函数多少次,模式正则表达式都只创建一次。

另一个用途是保持一个“随机”实例:

Function GetNextRandom() As Integer
Static r As New Random(getSeed())


Return r.Next()
End Function

此外,这不同于简单地将其声明为类的 Shared 成员; 以这种方式声明的项也保证是线程安全的。在这个场景中没有关系,因为表达式永远不会改变,但是在其他地方它可能会改变。

我非常喜欢在 VisualBasic2005中引入的 “我的”命名空间我的是获取多组信息和功能的捷径。它提供快速和直观的访问以下类型的信息:

  • 我的。电脑 : 获取与电脑有关的资讯,如文件系统、网络、设备、系统资讯等。它提供了对许多非常重要的资源的访问,包括 My。电脑。网络,我的。电脑。文件系统和我的。电脑。打印机。
  • 我的应用程序 : 获取与特定应用程序相关的信息,如名称、版本、工作目录等。
  • My.User : 访问与当前经过身份验证的用户相关的信息。
  • My.Resources : 以强类型方式访问驻留在资源文件中的应用程序所使用的资源。
  • My.Settings : 以强类型方式访问应用程序的配置设置。

可选参数

可选项比创建新的重载要容易得多,例如:

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
Console.Writeline(msg)
''//do stuff
End Function

通过名称传递参数,然后重新排序它们

Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)


'Do stuff


End function

用法:

Module Module1


Sub Main()


MyFunc() 'No params specified


End Sub


End Module

也可以使用“ : =”参数规范以任意顺序调用:

MyFunc(displayOrder:=10, msg:="mystring")

参数 的属性

我一直在做一些 C # 编程,发现 VB.Net 缺少一个特性,但这里没有提到。

如何做到这一点(以及 c # 限制)的示例可以在: 使用 C # 中带参数的典型 get set 属性上看到

我从答案中摘录了代码:

Private Shared m_Dictionary As IDictionary(Of String, Object) = _
New Dictionary(Of String, Object)


Public Shared Property DictionaryElement(ByVal Key As String) As Object
Get
If m_Dictionary.ContainsKey(Key) Then
Return m_Dictionary(Key)
Else
Return [String].Empty
End If
End Get
Set(ByVal value As Object)
If m_Dictionary.ContainsKey(Key) Then
m_Dictionary(Key) = value
Else
m_Dictionary.Add(Key, value)
End If


End Set
End Property

这是一个很好的例子。 VB.Net 中的 Select Case 语句非常强大。

当然有标准

Select Case Role
Case "Admin"
''//Do X
Case "Tester"
''//Do Y
Case "Developer"
''//Do Z
Case Else
''//Exception case
End Select

但还有更多..。

你可以做范围:

Select Case Amount
Case Is < 0
''//What!!
Case 0 To 15
Shipping = 2.0
Case 16 To 59
Shipping = 5.87
Case Is > 59
Shipping = 12.50
Case Else
Shipping = 9.99
End Select

甚至更多..。

您可以(尽管可能不是一个好主意)对多个变量进行布尔检查:

Select Case True
Case a = b
''//Do X
Case a = c
''//Do Y
Case b = c
''//Do Z
Case Else
''//Exception case
End Select

It's not possible to Explicitly implement interface members in VB, but it's possible to implement them with a different name.

Interface I1
Sub Foo()
Sub TheFoo()
End Interface


Interface I2
Sub Foo()
Sub TheFoo()
End Interface


Class C
Implements I1, I2


Public Sub IAmFoo1() Implements I1.Foo
' Something happens here'
End Sub


Public Sub IAmFoo2() Implements I2.Foo
' Another thing happens here'
End Sub


Public Sub TheF() Implements I1.TheFoo, I2.TheFoo
' You shouldn't yell!'
End Sub
End Class

请在 Microsoft Connect 为此特性投票。

一行代码可以有两行。因此:

Dim x As New Something : x.CallAMethod

在一行中可以有一个 If。

If True Then DoSomething()

VB 还提供了 OnError 语句,但是现在已经没什么用了。

On Error Resume Next
' Or'
On Error GoTo someline

您注意到 Like 比较运算符了吗?

Dim b As Boolean = “ file.txt”Like“ * . txt”

更多来自 MSDN

Dim testCheck As Boolean


' The following statement returns True (does "F" satisfy "F"?)'
testCheck = "F" Like "F"


' The following statement returns False for Option Compare Binary'
'    and True for Option Compare Text (does "F" satisfy "f"?)'
testCheck = "F" Like "f"


' The following statement returns False (does "F" satisfy "FFF"?)'
testCheck = "F" Like "FFF"


' The following statement returns True (does "aBBBa" have an "a" at the'
'    beginning, an "a" at the end, and any number of characters in '
'    between?)'
testCheck = "aBBBa" Like "a*a"


' The following statement returns True (does "F" occur in the set of'
'    characters from "A" through "Z"?)'
testCheck = "F" Like "[A-Z]"


' The following statement returns False (does "F" NOT occur in the '
'    set of characters from "A" through "Z"?)'
testCheck = "F" Like "[!A-Z]"


' The following statement returns True (does "a2a" begin and end with'
'    an "a" and have any single-digit number in between?)'
testCheck = "a2a" Like "a#a"


' The following statement returns True (does "aM5b" begin with an "a",'
'    followed by any character from the set "L" through "P", followed'
'    by any single-digit number, and end with any character NOT in'
'    the character set "c" through "e"?)'
testCheck = "aM5b" Like "a[L-P]#[!c-e]"


' The following statement returns True (does "BAT123khg" begin with a'
'    "B", followed by any single character, followed by a "T", and end'
'    with zero or more characters of any type?)'
testCheck = "BAT123khg" Like "B?T*"


' The following statement returns False (does "CAT123khg" begin with'
'    a "B", followed by any single character, followed by a "T", and'
'    end with zero or more characters of any type?)'
testCheck = "CAT123khg" Like "B?T*"

有一天 Basic 用户没有引入任何变量。他们只是通过使用它们来介绍它们。VB 的 OptionExplicity 的引入只是为了确保您不会因为错误的输入而错误地引入任何变量。您可以随时关闭它,体验我们使用 Basic 的日子。

在 VB8和以前的版本中,如果没有为引入的变量指定任何类型,则会自动检测到 Object 类型。在 VB9(2008)中,如果 OptionInfer 设置为 On (默认情况下是 On) ,则 Dim的作用类似于 C # 的 var关键字

我刚发现一篇文章谈论“ !”操作符,也称为“字典查找操作符”。以下是本文节选自: http://panopticoncentral.net/articles/902.aspx

操作符的技术名称 是“字典查找操作符” Dictionary 是指任何集合类型 是通过键而不是通过 number, just like the way that the entries in an English dictionary are 由您想要的单词索引 最常见的例子 属于字典类型的是 系统,集合,哈希表,哪个 允许您添加(键,值)对 然后检索 值。例如, 下面的代码添加了三个条目 散列表,看起来就是其中之一 用“猪肉”这个键。

Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat"
Console.WriteLine(Table("Pork"))

The ! operator can be used to look up 来自任何字典类型的值 使用字符串对其值进行索引 标识符之后,将! 用作 key in the lookup operation. So the 上面的代码本来可以是 写道:

Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)

第二个例子是 相当于第一个,但只是 looks a lot nicer, at least to my eyes. I find that there are a lot of 可以使用! 的地方,尤其是 当涉及到 XML 和网络时, 那里有成吨的 索引的集合 string. One unfortunate limitation is 那个跟在后面的东西 必须是有效的标识符,所以如果 要用作键的字符串 有一些无效的标识符字符 在里面,你不能使用! 操作员。 (例如,你不能说 “ Table! AB $CD = 5”因为 $不是 在 VB6和 before, you could use brackets to 转义无效的标识符(即。 “桌子! [ AB $CD ]”) ,但当我们开始 使用括号转义关键字时,我们 失去了做到这一点的能力。在大多数情况下 然而,这并不是太多 一个限制。

更专业的说,x! y 在下列情况下工作 X 有一个默认属性,该属性接受 字符串或对象作为参数 在这种情况下,x! y 变成 x.DefaultProperty("y"). An interesting 边注是,有一个特别的 的词汇语法中的规则 语言使这一切工作! 字符也用作类型 字符的语言,和类型 字符在运算符之前被吃掉。 So without a special rule, x!y would 被扫描为“ x! y”而不是“ x!”! 幸运的是,由于没有 在语言中有两个地方 行中的标识符是有效的,则我们 只是引入了一个规则,如果 在! 之后的下一个字符是 开始一个标识符,我们认为 是操作符而不是类型 character.

关键字提供了一种方法来引用最初实现的类实例成员,忽略任何派生类重写。

选择 Case 代替多个 If/ElseIf/Else 语句。

在这个例子中假设简单的几何对象:

Function GetToString(obj as SimpleGeomertyClass) as String
Select Case True
Case TypeOf obj is PointClass
Return String.Format("Point: Position = {0}", _
DirectCast(obj,Point).ToString)
Case TypeOf obj is LineClass
Dim Line = DirectCast(obj,LineClass)
Return String.Format("Line: StartPosition = {0}, EndPosition = {1}", _
Line.StartPoint.ToString,Line.EndPoint.ToString)
Case TypeOf obj is CircleClass
Dim Line = DirectCast(obj,CircleClass)
Return String.Format("Circle: CenterPosition = {0}, Radius = {1}", _
Circle.CenterPoint.ToString,Circle.Radius)
Case Else
Return String.Format("Unhandled Type {0}",TypeName(obj))
End Select
End Function

堆栈/组多个 using 语句在一起:

Dim sql As String = "StoredProcedureName"
Using cn As SqlConnection = getOpenConnection(), _
cmd As New SqlCommand(sql, cn), _
rdr As SqlDataReader = cmd.ExecuteReader()


While rdr.Read()


''// Do Something


End While


End Using

公平地说,你也可以用 C # 来做。但是很多人对这两种语言都不了解。

最好、最简单的 CSV 解析器:

Microsoft.VisualBasic.FileIO.TextFieldParser

By adding a reference to Microsoft.VisualBasic, this can be used in any other .Net language, e.g. C#

类似于 Parsa 的的答案,就像接线员很多的东西,它可以在简单通配符以上进行匹配。读到上面的 MSDN 文档时,我差点从椅子上摔下来: -)

DateTime 可以通过用 # 围绕您的日期进行初始化

Dim independanceDay As DateTime = #7/4/1776#

还可以在使用此语法的同时使用类型推断

Dim independanceDay = #7/4/1776#

这比使用构造函数好多了

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)

在 vb 中,这些运算符之间有一个区别:

/Double
\ is Integer ignoring the remainder

Sub Main()
Dim x = 9 / 5
Dim y = 9 \ 5
Console.WriteLine("item x of '{0}' equals to {1}", x.GetType.FullName, x)
Console.WriteLine("item y of '{0}' equals to {1}", y.GetType.FullName, y)


'Results:
'item x of 'System.Double' equals to 1.8
'item y of 'System.Int32' equals to 1
End Sub

如果你从来不知道下面的内容,你真的不会相信它是真的,这是 C # 真正缺少的东西:

(它被称为 XML 文本)

Imports <xmlns:xs="System">


Module Module1


Sub Main()
Dim xml =
<root>
<customer id="345">
<name>John</name>
<age>17</age>
</customer>
<customer id="365">
<name>Doe</name>
<age>99</age>
</customer>
</root>


Dim id = 1
Dim name = "Beth"
DoIt(
<param>
<customer>
<id><%= id %></id>
<name><%= name %></name>
</customer>
</param>
)


Dim names = xml...<name>
For Each n In names
Console.WriteLine(n.Value)
Next


For Each customer In xml.<customer>
Console.WriteLine("{0}: {1}", customer.@id, customer.<age>.Value)
Next


Console.Read()
End Sub


Private Sub CreateClass()
Dim CustomerSchema =
XDocument.Load(CurDir() & "\customer.xsd")


Dim fields =
From field In CustomerSchema...<xs:element>
Where field.@type IsNot Nothing
Select
Name = field.@name,
Type = field.@type


Dim customer =
<customer> Public Class Customer
<%= From field In fields Select <f>
Private m_<%= field.Name %> As <%= GetVBPropType(field.Type) %></f>.Value %>


<%= From field In fields Select <p>
Public Property <%= field.Name %> As <%= GetVBPropType(field.Type) %>
Get
Return m_<%= field.Name %>
End Get
Set(ByVal value As <%= GetVBPropType(field.Type) %>)
m_<%= field.Name %> = value
End Set
End Property</p>.Value %>
End Class</customer>


My.Computer.FileSystem.WriteAllText("Customer.vb",
customer.Value,
False,
System.Text.Encoding.ASCII)


End Sub


Private Function GetVBPropType(ByVal xmlType As String) As String
Select Case xmlType
Case "xs:string"
Return "String"
Case "xs:int"
Return "Integer"
Case "xs:decimal"
Return "Decimal"
Case "xs:boolean"
Return "Boolean"
Case "xs:dateTime", "xs:date"
Return "Date"
Case Else
Return "'TODO: Define Type"
End Select
End Function


Private Sub DoIt(ByVal param As XElement)
Dim customers =
From customer In param...<customer>
Select New Customer With
{
.ID = customer.<id>.Value,
.FirstName = customer.<name>.Value
}


For Each c In customers
Console.WriteLine(c.ToString())
Next
End Sub


Private Class Customer
Public ID As Integer
Public FirstName As String
Public Overrides Function ToString() As String
Return <string>
ID : <%= Me.ID %>
Name : <%= Me.FirstName %>
</string>.Value
End Function


End Class
End Module
'Results:


ID : 1
Name : Beth
John
Doe
345: 17
365: 99

Take a look at XML 文字技巧 by Beth Massi.

Sub Main()
Select Case "value to check"
'Check for multiple items at once:'
Case "a", "b", "asdf"
Console.WriteLine("Nope...")
Case "value to check"
Console.WriteLine("Oh yeah! thass what im talkin about!")
Case Else
Console.WriteLine("Nah :'(")
End Select




Dim jonny = False
Dim charlie = True
Dim values = New String() {"asdff", "asdfasdf"}
Select Case "asdfasdf"
'You can perform boolean checks that has nothing to do with your var.,
'not that I would recommend that, but it exists.'
Case values.Contains("ddddddddddddddddddddddd")
Case True
Case "No sense"
Case Else
End Select


Dim x = 56
Select Case x
Case Is > 56
Case Is <= 5
Case Is <> 45
Case Else
End Select


End Sub

与 C # 不同,在 VB 中,你可以依赖于不可空项的默认值:

Sub Main()
'Auto assigned to def value'
Dim i As Integer '0'
Dim dt As DateTime '#12:00:00 AM#'
Dim a As Date '#12:00:00 AM#'
Dim b As Boolean 'False'


Dim s = i.ToString 'valid
End Sub

而在 C # 中,这将是一个编译器错误:

int x;
var y = x.ToString(); //Use of unassigned value
IIf(False, MsgBox("msg1"), MsgBox("msg2"))

What is the result? two message boxes!!!! This happens cuz the IIf function evaluates both parameters when reaching the function.

VB 有一个新的 If 操作符(就像 C # ? : 操作符一样) :

If(False, MsgBox("msg1"), MsgBox("msg2"))

将只显示第二个 msgbox。

一般情况下,我建议替换 vb 代码中的所有 IIF,除非您希望它同时评估以下两项:

Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())

可以确保两个值都已加载。

如果用[和]包围名称,则可以对属性和变量名称使用保留关键字

Public Class Item
Private Value As Integer
Public Sub New(ByVal value As Integer)
Me.Value = value
End Sub


Public ReadOnly Property [String]() As String
Get
Return Value
End Get
End Property


Public ReadOnly Property [Integer]() As Integer
Get
Return Value
End Get
End Property


Public ReadOnly Property [Boolean]() As Boolean
Get
Return Value
End Get
End Property
End Class


'Real examples:
Public Class PropertyException : Inherits Exception
Public Sub New(ByVal [property] As String)
Me.Property = [property]
End Sub


Private m_Property As String
Public Property [Property]() As String
Get
Return m_Property
End Get
Set(ByVal value As String)
m_Property = value
End Set
End Property
End Class


Public Enum LoginLevel
[Public] = 0
Account = 1
Admin = 2
[Default] = Account
End Enum
Private Sub Button1_Click(ByVal sender As Button, ByVal e As System.EventArgs)
Handles Button1.Click
sender.Enabled = True
DisableButton(sender)
End Sub


Private Sub Disable(button As Object)
button.Enabled = false
End Sub

在这个代码片段中,有两个(也许更多?)你在 C # 中永远不可能做到的事情:

  1. 处理 Button1.Click-在外部将处理程序附加到事件!
  2. VB 的隐式允许您将处理程序的第一个参数声明为期望类型。在 C # 中,您不能将委托定位到不同的模式,即使它是预期的类型。

另外,在 C # 中,你不能在对象上使用期望的功能——在 C # 中,你可以梦想它(现在他们创建了 Dynamic 关键字,但是它远离 VB)。 在 C # 中,如果你写(new object ())。“启用”将得到一个错误,即类型对象没有“启用”方法。 Now, I am not the one who will recommend you if this is safe or not, the info is provided AS IS, do on your own, bus still, sometimes (like when working with COM objects) this is such a good thing. 当期望值肯定是一个按钮时,我个人总是写(发送方为按钮)。

实际上,举个例子:

Private Sub control_Click(ByVal sender As Control, ByVal e As System.EventArgs)
Handles TextBox1.Click, CheckBox1.Click, Button1.Click
sender.Text = "Got it?..."
End Sub

作者: ValByRef关键词的区别:

Module Module1


Sub Main()
Dim str1 = "initial"
Dim str2 = "initial"
DoByVal(str1)
DoByRef(str2)


Console.WriteLine(str1)
Console.WriteLine(str2)
End Sub


Sub DoByVal(ByVal str As String)
str = "value 1"
End Sub


Sub DoByRef(ByRef str As String)
str = "value 2"
End Sub
End Module


'Results:
'initial
'value 2

我发现有一个特性非常有用,并且有助于解决许多 bug,那就是显式地向函数传递参数,特别是在使用可选参数时。

Here is an example:

Public Function DoSomething(byval x as integer, optional y as boolean=True, optional z as boolean=False)
' ......
End Function

你可以这么说:

DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)

这样调用这个函数会更简单,没有错误

DoSomething(1,true)

Nothing 关键字可以表示 default (T)或 null,具体取决于上下文。你可以利用这一点来制作一个非常有趣的方法:

'''<summary>Returns true for reference types, false for struct types.</summary>'
Public Function IsReferenceType(Of T)() As Boolean
Return DirectCast(Nothing, T) Is Nothing
End Function

使用 When 精化错误处理

注意 Catch ex As IO.FileLoadException When attempt < 3行中使用的 when

Do
Dim attempt As Integer
Try
''// something that might cause an error.
Catch ex As IO.FileLoadException When attempt < 3
If MsgBox("do again?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
Exit Do
End If
Catch ex As Exception
''// if any other error type occurs or the attempts are too many
MsgBox(ex.Message)
Exit Do
End Try
''// increment the attempt counter.
attempt += 1
Loop

最近在 VbRad频道播出

When declaring an array in vb.net always use the "0 to xx" syntax.

Dim b(0 to 9) as byte 'Declares an array of 10 bytes

它非常清楚数组的跨度

Dim b(9) as byte 'Declares another array of 10 bytes

即使您知道第二个示例由10个元素组成,也不会感觉很明显。我已经记不清有多少次,我看到一个程序员想要上面的代码,但是却写了

Dim b(10) as byte 'Declares another array of 10 bytes

这当然是完全错误的。因为 b (10)创建了一个11字节的数组。而且它很容易引起错误,因为对于不知道要查找什么的人来说,它看起来是正确的。

“0 to xx”语法也适用于以下情况

Dim b As Byte() = New Byte(0 To 9) {} 'Another way to create a 10 byte array
ReDim b(0 to 9) 'Assigns a new 10 byte array to b

通过使用完整的语法,您还可以向将来读取您的代码的任何人演示,您知道自己在做什么。

这里有一个有趣的我没有看到,我知道它的工作在 VS 2008,至少:

如果你不小心以分号 结束你的 VB 行,因为你已经做了太多的 C # ,分号会自动删除。实际上(至少在 VS2008中)不可能意外地以分号结束 VB 行。试试看!

(它并不完美; 如果在最终的类名中间键入分号,它就不会自动完成类名。)

There are a couple of answers about XML Literals, but not about this specific case:

可以使用 XMLLiterals 封装否则需要转义的字符串文字。例如,包含双引号的字符串文字。

而不是这样:

Dim myString = _
"This string contains ""quotes"" and they're ugly."

You can do this:

Dim myString = _
<string>This string contains "quotes" and they're nice.</string>.Value

如果您正在测试一个用于 CSV 解析的文本,这尤其有用:

Dim csvTestYuck = _
"""Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""


Dim csvTestMuchBetter = _
<string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value

(当然,您不必使用 <string>标记; 您可以使用任何您喜欢的标记。)

强迫 ByVal

在 VB 中,如果用一组额外的括号包装参数,就可以覆盖该方法的 ByRef 声明,并将其转换为 ByVal。例如,下面的代码生成4、5、5,而不是4、5、6

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim R = 4
Trace.WriteLine(R)
Test(R)
Trace.WriteLine(R)
Test((R))
Trace.WriteLine(R)
End Sub
Private Sub Test(ByRef i As Integer)
i += 1
End Sub

参见 不被过程调用底层变量修改的参数

The Me Keyword

“ Me”关键字在 VB.Net 中是唯一的。我知道这很常见,但是在“ Me”和 C # 等价物“ this”之间是有区别的。区别在于“ this”是只读的,而“ Me”不是。这在构造函数中很有价值,因为在构造函数中,你需要一个变量的实例,你希望变量被构造成相等的,因为你可以只设置“ Me = TheVariable”,而不是 C # ,在 C # 中,你需要手动复制变量的每个字段(如果有很多字段,并且容易出错,这会很可怕)。C # 工作区将在构造函数之外执行赋值操作。也就是说,如果对象是自我构造成一个完整的对象,那么现在需要另一个函数。

方法的属性!例如,一个在设计期间不应该可用的属性可以1)隐藏在属性窗口中,2)没有序列化(对于用户控件或从数据库加载的控件来说尤其烦人) :

<System.ComponentModel.Browsable(False), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AUX_ID() As String
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return mAUX_ID
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As String)
mAUX_ID = value
End Set
End Property

如果进行了大量的调试,那么输入 DebuggerStepThrough()也是 很有帮助(注意,仍然可以在函数或其他内容中放入断点,但是不能单步执行该函数)。

Also, the ability to put things in categories (e.g., "Data") means that, if you want the property to show up in the properties tool-window, that particular property will show up in that category.

无效日期!在数据库(在本例中是 MSSQLServer)中有数据进出的情况下,这尤其有用。我有两个过程来给我一个 SmallDateTime 参数,并用一个值填充它。其中一个工具接受一个普通的旧日期并测试其中是否有任何值,分配一个默认日期。另一个版本接受 Nullable(Of Date),这样我就可以让日期没有值,接受来自存储过程的默认值

<System.Diagnostics.DebuggerStepThrough> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Date) As SqlParameter
Dim aParm As SqlParameter = New SqlParameter
Dim unDate As Date
With aParm
.ParameterName = strName
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.SmallDateTime
If unDate = dtValue Then    'Unassigned variable
.Value = "1/1/1900 12:00:00 AM" 'give it a default which is accepted by smalldatetime
Else
.Value = CDate(dtValue.ToShortDateString)
End If
End With
Return aParm
End Function
<System.Diagnostics.DebuggerStepThrough()> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Nullable(Of Date)) As SqlParameter
Dim aParm As SqlParameter = New SqlParameter
Dim unDate As Date
With aParm
.ParameterName = strName
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.SmallDateTime
If dtValue.HasValue = False Then
'// it's nullable, so has no value
ElseIf unDate = dtValue.Value Then    'Unassigned variable
'// still, it's nullable for a reason, folks!
Else
.Value = CDate(dtValue.Value.ToShortDateString)
End If
End With
Return aParm
End Function

与 C 语言中的 break不同,VB 中你可以选择 Exit或者 Continue的代码块:

For i As Integer = 0 To 100
While True
Exit While
Select Case i
Case 1
Exit Select
Case 2
Exit For
Case 3
Exit While
Case Else
Exit Sub
End Select
Continue For
End While
Next

代码文档

''' <summary>
'''
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub

又是可选参数!

Function DoSmtg(Optional a As string, b As Integer, c As String)
'DoSmtg
End


' Call
DoSmtg(,,"c argument")


DoSmtg(,"b argument")