我已经通过浏览C# 的隐藏特性学到了很多东西,当我找不到与 VB.NET 类似的东西时,我感到很惊讶。
那么它的一些隐藏或鲜为人知的功能是什么?
我已经通过浏览C# 的隐藏特性学到了很多东西,当我找不到与 VB.NET 类似的东西时,我感到很惊讶。
那么它的一些隐藏或鲜为人知的功能是什么?
该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
Enum
_VB真正隐藏completionlist
的特性之一是XML 文档标记,可用于创建Enum
具有扩展功能的类似自己的类型。但是,此功能在 C# 中不起作用。
我最近的代码中的一个示例:
'
''' <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 会提供一个 IntelliSense 列表,其中包含RuleTemplates
.
由于这是一个依赖于 IDE 的功能,因此在使用它时很难展示它的外观,但我将仅使用屏幕截图:
完成列表在行动 http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png
事实上,IntelliSense 与使用Enum
.
你注意到 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*"
VB 知道一种原始的typedef
通过Import
别名:
Imports S = System.String
Dim x As S = "Hello"
这在与泛型类型结合使用时更有用:
Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
哦!并且不要忘记XML Literals。
Dim contact2 = _
<contact>
<name>Patrick Hines</name>
<%= From p In phoneNumbers2 _
Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
%>
</contact>
对象初始化也在那里!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
DirectCast
DirectCast
是一个奇迹。从表面上看,它的工作原理类似于CType
运算符,因为它将对象从一种类型转换为另一种类型。但是,它遵循一套更严格的规则。CType
因此, 的实际行为通常是不透明的,并且执行哪种转换完全不明显。
DirectCast
仅支持两种不同的操作:
Integer
任何其他强制转换都将不起作用(例如,尝试将 an 拆箱Double
)并将导致编译时/运行时错误(取决于情况和静态类型检查可以检测到的内容)。因此,我DirectCast
尽可能使用它,因为这最能体现我的意图:根据具体情况,我要么对已知类型的值进行拆箱,要么执行向上转型。故事结局。
CType
另一方面,使用让代码的读者想知道程序员的真正意图是什么,因为它可以解析各种不同的操作,包括调用用户定义的代码。
为什么这是一个隐藏功能?VB 团队发布了一个指导方针1,不鼓励使用DirectCast
(即使它实际上更快!)以使代码更加统一。我认为这是一个糟糕的指导方针,应该颠倒过来:只要有可能,优先DirectCast
考虑更通用的CType
运算符。它使代码更清晰。CType
另一方面,只有在确实是这样的情况下才应该调用,即当一个窄化CType
运算符(参见运算符重载)应该被调用时。
1)我无法提供该指南的链接,但我发现Paul Vick对此表示赞同(VB 团队的首席开发人员):
在现实世界中,您几乎不会注意到差异,因此您不妨使用更灵活的转换运算符,如 CType、CInt 等。
(Zack 编辑:在此处了解更多信息:我应该如何在 VB.NET 中进行投射?)
If
条件和合并运算符我不知道你会怎么称呼它,但是 Iif([expression],[value if true],[value if false]) As Object 函数可以计数。
它不像被弃用那样隐藏!VB 9 具有If
更好的运算符,并且与 C# 的条件和合并运算符完全相同(取决于您想要什么):
Dim x = If(a = b, c, d)
Dim hello As String = Nothing
Dim y = If(hello, "World")
编辑以显示另一个示例:
这将适用于If()
,但会导致异常IIf()
Dim x = If(b<>0,a/b,0)
这是一个不错的。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
我一直使用的一个主要的省时方法是With关键字:
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
我只是不喜欢打字超过我必须的!
最好和最简单的 CSV 解析器:
Microsoft.VisualBasic.FileIO.TextFieldParser
通过添加对 Microsoft.VisualBasic 的引用,这可以在任何其他 .Net 语言中使用,例如 C#
(编辑:在此处了解更多信息:我应该始终使用 AndAlso 和 OrElse 运算符吗?)
方法中的静态成员。
例如:
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 成员不同;以这种方式声明的项目也保证是线程安全的。在这种情况下这无关紧要,因为表达式永远不会改变,但在其他情况下它可能会改变。
在 vb 中,这些运算符之间存在差异:
/
is忽略余Double
\
数Integer
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
虽然很少有用,但事件处理可以大量定制:
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
我非常喜欢Visual Basic 2005 中引入的“My”命名空间。My是多组信息和功能的快捷方式。它提供对以下类型信息的快速直观的访问:
我刚刚发现一篇关于“!”的文章。运算符,也称为“字典查找运算符”。以下是文章摘录:http: //panopticoncentral.net/articles/902.aspx
的技术名称!运算符是“字典查找运算符”。字典是由键而不是数字索引的任何集合类型,就像英语词典中的条目由您想要定义的单词索引的方式一样。字典类型最常见的示例是 System.Collections.Hashtable,它允许您将(键、值)对添加到哈希表中,然后使用键检索值。例如,以下代码将三个条目添加到哈希表,并使用键“Pork”查找其中一个。
Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat"
Console.WriteLine(Table("Pork"))
这 !运算符可用于从任何使用字符串索引其值的字典类型中查找值。! 之后的标识符 用作查找操作中的键。所以上面的代码可以改为:
Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)
第二个例子完全等同于第一个,但看起来好多了,至少在我看来。我发现有很多地方!可以使用,尤其是在涉及到 XML 和 Web 时,其中只有大量由字符串索引的集合。一个不幸的限制是 ! 仍然必须是一个有效的标识符,所以如果你想用作键的字符串中有一些无效的标识符字符,你不能使用 ! 操作员。(例如,您不能说“Table!AB$CD = 5”,因为 $ 在标识符中是不合法的。)在 VB6 及之前的版本中,您可以使用括号来转义无效的标识符(即“Table![AB$ CD]"),但是当我们开始使用方括号来转义关键字时,我们就失去了这样做的能力。在大多数情况下,
要获得真正的技术性,如果 x 具有将字符串或对象作为参数的默认属性,则 x!y 有效。在这种情况下,x!y 将更改为 x.DefaultProperty("y")。一个有趣的旁注是,该语言的词汇语法中有一条特殊规则可以使这一切正常工作。这 !字符在语言中也被用作类型字符,类型字符在运算符之前被吃掉。因此,如果没有特殊规则,x!y 将被扫描为“x!y”而不是“x!y”。幸运的是,由于语言中没有连续两个标识符有效的地方,我们只是引入了规则,如果 ! 之后的下一个字符 是标识符的开始,我们考虑!成为运算符而不是类型字符。
这是内置的,与 C# 相比具有明显优势。无需使用相同名称即可实现接口方法的能力。
如:
Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo
End Sub
强制 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
按名称传递参数,并重新排序它们
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")
从 VB 8 开始,Using 语句是新的,C# 从一开始就有它。它会自动为您调用 dispose。
例如
Using lockThis as New MyLocker(objToLock)
End Using
导入别名在很大程度上也是未知的:
Import winf = System.Windows.Forms
''Later
Dim x as winf.Form
如果您需要一个变量名称来匹配关键字的名称,请用括号括起来。不是。虽然是最佳实践 - 但可以明智地使用它。
例如
Class CodeException
Public [Error] as String
''...
End Class
''later
Dim e as new CodeException
e.Error = "Invalid Syntax"
例如来自评论的示例(@Pondidum):
Class Timer
Public Sub Start()
''...
End Sub
Public Sub [Stop]()
''...
End Sub
考虑以下事件声明
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
关于 XML Literals 有几个答案,但不是关于这个特定案例:
您可以使用 XML Literals 来包含原本需要转义的字符串文字。例如,包含双引号的字符串文字。
而不是这个:
Dim myString = _
"This string contains ""quotes"" and they're ugly."
你可以这样做:
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>
标签;您可以使用任何您喜欢的标签。)
您可以在一行中包含 2 行代码。因此:
Dim x As New Something : x.CallAMethod
DateTime 可以通过用 # 包围您的日期来初始化
Dim independanceDay As DateTime = #7/4/1776#
您还可以将类型推断与此语法一起使用
Dim independanceDay = #7/4/1776#
这比使用构造函数要好得多
Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
可选参数
可选项比创建新的重载要容易得多,例如:
Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
Console.Writeline(msg)
''//do stuff
End Function
带参数的属性
我一直在做一些 C# 编程,并发现了 VB.Net 缺少的一个特性,但这里没有提到。
可以在以下位置查看如何执行此操作的示例(以及 c# 限制):Using thetypical get set properties in C#... with parameters
我从那个答案中摘录了代码:
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 中的标题案例可以通过旧的 VB6 fxn 实现:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
将多个 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# 中做到这一点。但是很多人在这两种语言中都不知道这一点。
我发现真正有用并有助于解决许多错误的功能之一是显式地将参数传递给函数,尤其是在使用可选时。
这是一个例子:
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)
您可以在一行中有一个 If。
If True Then DoSomething()
如果您不知道以下内容,您真的不会相信这是真的,这确实是 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
看看Beth Massi 的XML Literals Tips/Tricks。
注意when
行中的使用Catch ex As IO.FileLoadException When attempt < 3
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中查看
这是一个我没见过的有趣的;我知道它至少在 VS 2008 中有效:
如果你不小心用分号结束了你的 VB 行,因为你已经做了太多的 C#,分号会被自动删除。实际上不可能(同样,至少在 VS 2008 中)意外地用分号结束 VB 行。试试看!
(这并不完美;如果您在最终类名的中间键入分号,它不会自动完成类名。)
与break
VB 中的 C 语言不同,您可以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
Select Case in place of multiple If/ElseIf/Else statements.
Assume simple geometry objects in this example:
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
在 VB8 及以前的版本中,如果您没有为您引入的变量指定任何类型,则会自动检测 Object 类型。在 VB9 (2008) 中,如果 Option Infer 设置为 On(默认情况下) ,则Dim
将像 C# 的关键字一样var
IIf(False, MsgBox("msg1"), MsgBox("msg2"))
结果是什么?两个消息框!!!!发生这种情况是因为 IIf 函数在到达该函数时会评估这两个参数。
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
在 vb.net 中声明数组时,始终使用“0 到 xx”语法。
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
通过使用完整的语法,您还将向将来阅读您的代码的任何人展示您知道自己在做什么。
记住 VB.NET 项目默认情况下具有作为项目属性一部分的根命名空间也很重要。默认情况下,此根命名空间将与项目具有相同的名称。当使用命名空间块结构时,名称实际上附加到该根命名空间。例如:如果项目名为 MyProject,那么我们可以将变量声明为:
Private obj As MyProject.MyNamespace.MyClass
要更改根命名空间,请使用 Project -> Properties 菜单选项。根命名空间也可以被清除,这意味着所有命名空间块都成为它们包含的代码的根级别。
MyClass 关键字提供了一种方法来引用最初实现的类实例成员,忽略任何派生类覆盖。
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
可能这个链接应该有帮助
http://blogs.msdn.com/vbteam/archive/2007/11/20/hidden-gems-in-visual-basic-2008-amanda-silver.aspx
与 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
别名命名空间
Imports Lan = Langauge
虽然不是 VB.Net 独有的,但在遇到命名空间冲突时经常会被遗忘。
VB 还提供了 OnError 语句。但是这些天它并没有多大用处。
On Error Resume Next
' Or'
On Error GoTo someline
我不知道你会说它有多隐蔽,但If
接线员可以数数。
在某种程度上,它与许多类 C 语言中的?:
(三元)或运算符非常相似。??
但是,重要的是要注意它确实评估了所有参数,因此重要的是不要传递任何可能导致异常(除非你想要它)或任何可能导致意外副作用的东西。
用法:
Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
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
在此代码段中,您有 2 件(也许更多?)您在 C# 中永远无法做到的事情:
此外,在 C# 中,您不能在对象上使用预期的功能 - 在 C# 中,您可以梦想它(现在他们制作了 dynamic 关键字,但它与 VB 相去甚远)。在 C# 中,如果您编写 (new object()).Enabled,您将收到类型对象没有方法“启用”的错误。现在,我不是会推荐你的人,如果这是否安全,信息是按原样提供的,你自己做,仍然是总线,有时(比如在使用 COM 对象时)这是一件好事。当期望值肯定是一个按钮时,我个人总是写 (sender As Button)。
实际上此外:举这个例子:
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
在 VB 中无法显式实现接口成员,但可以使用不同的名称实现它们。
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
您可以使用 REM 注释掉一行而不是 ' 。不是超级有用,但可以帮助重要的评论脱颖而出,而无需使用“!!!!!!!!!” 管他呢。
可空日期!这在您有数据输入/输出数据库(在本例中为 MSSQL Server)的情况下特别有用。我有两个过程给我一个 SmallDateTime 参数,填充了一个值。其中一个获取一个普通的旧日期并测试它是否有任何值,分配一个默认日期。另一个版本接受 aNullable(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
Documentation of code
''' <summary>
'''
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
我以前很喜欢可选的函数参数,但现在我用得更少了,因为我经常在 C# 和 VB 之间来回穿梭。C# 什么时候支持它们?C++ 甚至 C 都有它们(某种意义上的)!
有一天,基本用户没有引入任何变量。他们只是通过使用它们来介绍它们。VB 的 Option Explicit 被引入只是为了确保您不会因输入错误而错误地引入任何变量。您可以随时将其关闭,体验我们使用 Basic 的日子。
ByVal和ByRef关键字的区别:
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
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
又是可选参数!
Function DoSmtg(Optional a As string, b As Integer, c As String)
'DoSmtg
End
' Call
DoSmtg(,,"c argument")
DoSmtg(,"b argument")
方法的属性!例如,在设计时不应该可用的属性可以是 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()
如果您进行任何数量的调试,放入也非常有帮助(请注意,您仍然可以在函数或其他任何内容中放置断点,但您不能单步执行该函数)。
此外,将事物分类(例如,“数据”)的能力意味着,如果您确实希望该属性显示在属性工具窗口中,则该特定属性将显示在该类别中。
我的关键字
“我”关键字在 VB.Net 中是独一无二的。我知道这很常见,但是“Me”和 C# 等效的“this”之间是有区别的。区别在于“this”是只读的,而“Me”不是。这在你有一个变量实例的构造函数中很有价值,你希望该变量已经被构造为相等,因为你可以设置“Me = TheVariable”,而不是在 C# 中你必须手动复制变量的每个字段(其中如果有很多字段并且容易出错,那可能会很糟糕)。C# 的解决方法是在构造函数之外进行赋值。这意味着你现在如果对象是自构造成一个完整的对象,你现在需要另一个函数。