VB.NET的隐藏function?
我已经通过C#的隐藏特性了解了很多浏览内容,当我找不到类似于VB.NET的东西时,感到惊讶。
那么它的一些隐藏或较less已知的function是什么?
子句时的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真正隐藏的function之一是completionlist
XML文档标签,可用于创build具有扩展function的自己类Enum
types。 虽然这个function在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
的variables赋值时,IDE提供一个来自RuleTemplates
的可能值的智能感知列表。
/编辑:
由于这是一个依赖于IDE的function,因此很难在使用它时显示它的外观,但是我只是使用屏幕截图:
完成列表在行动http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png
事实上,智能感知与使用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 "[AZ]" ' The following statement returns False (does "F" NOT occur in the ' ' set of characters from "A" through "Z"?)' testCheck = "F" Like "[!AZ]" ' 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[LP]#[!ce]" ' 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*"
types定义
VB通过Import
别名知道一种原始types的typedef
:
Imports S = System.String Dim x As S = "Hello"
与generics一起使用时,这更有用:
Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
哦! 不要忘记XML文字 。
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
运算符类似,它将对象从一种types转换为另一种types。 然而,它的工作更严格的一套规则。 CType
的实际行为往往是不透明的,而且执行哪种转换并不明显。
DirectCast
只支持两种不同的操作:
- 取消装箱的值types和
- 在类层次结构中向上转换。
任何其他的强制转换都不起作用(例如试图将Integer
转换为Double
),并且会导致编译时/运行时错误(取决于情况以及静态types检查可以检测到什么)。 因此,我会尽可能使用DirectCast
,因为这样可以最好地捕捉我的意图:根据具体情况,我可能要取消已知types的值或执行upcast。 故事结局。
另一方面,使用CType
会让代码的读者不知道程序员的真正意图,因为它解决了各种不同的操作,包括调用用户定义的代码。
为什么这是一个隐藏的function? VB小组已经发布了一个指导方针1 ,它不鼓励使用DirectCast
(即使速度更快!),以使代码更加统一。 我认为这是一个不好的指导方针,应该颠倒: 只要有可能,赞成DirectCast
而不是更一般的CType
运算符。 它使代码更清晰。 另一方面, CType
只有在确实有意的时候才能被调用,也就是说,应该调用一个缩小的CType
运算符(参见运算符重载 )。
1)我找不到指南的链接,但是我发现Paul Vick是这样做的 (VB团队的首席开发人员):
在现实世界中,你几乎不会注意到其中的差异,所以你最好还是使用像CType,CInt等更灵活的转换运算符。
(由Zack编辑:在这里了解更多: 我应该怎样在VB.NET中投入? )
If
有条件和合并操作符
我不知道你会怎样调用它,但是Iif([expression式],[值如果为真],[值如果为false])作为对象函数可以计数。
它不像已弃用那么隐蔽! VB 9的If
运算符要好得多,并且和C#的条件运算符一样(取决于你想要的):
Dim x = If(a = b, c, d) Dim hello As String = Nothing Dim y = If(hello, "World")
编辑来显示另一个例子:
这将与If()
,但是会导致IIf()
的exception
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
甚至更多…
你可以(虽然可能不是个好主意)对多个variables进行布尔检查:
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
我只是不喜欢打字比我必须!
最好的和容易的CSVparsing器:
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
在上面的函数中,模式正则expression式只能被创build一次,无论调用多less次函数。
另一个用途是保持“随机”的实例:
Function GetNextRandom() As Integer Static r As New Random(getSeed()) Return r.Next() End Function
此外,这与简单地将其声明为该类的共享成员并不相同; 以这种方式声明的项目也保证是线程安全的。 在这种情况下并不重要,因为expression将永远不会改变,但也有其他的地方可能。
在VB中这些操作符有所不同:
/
是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
我非常喜欢在Visual Basic 2005中引入的“我的”命名空间 。 我是几组信息和function的快捷方式。 它提供了对以下types信息的快速直观访问:
- My.Computer :访问与计算机相关的信息,如文件系统,networking,设备,系统信息等。它提供了许多非常重要的资源,包括My.Computer.Network,My.Computer.FileSystem和My .Computer.Printers。
- My.Application :访问与特定应用程序相关的信息,如名称,版本,当前目录等
- My.User :访问与当前authentication用户相关的信息。
- My.Resources :以强types方式访问驻留在资源文件中的应用程序使用的资源。
- My.Settings :以强types的方式访问应用程序的configuration设置。
自定义事件
虽然很less有用,事件处理可以大量定制:
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
这可以按照以下方式进行testing:
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
我刚刚find一篇文章谈论“!” 运算符,也称为“字典查找运算符”。 以下是文章摘录: http : //panopticoncentral.net/articles/902.aspx
!的技术名称! 操作符是“字典查找操作符”。 字典是任何一种按键索引而不是数字索引的集合types,就像英文词典中的条目按照您希望定义的词索引的方式一样。 字典types的最常见示例是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"))
那! 运算符可用于从任何使用string索引其值的字典types查找值。 !!之后的标识符 在查找操作中用作键。 所以上面的代码可以写成:
Dim Table As Hashtable = New Hashtable Table!Orange = "A fruit" Table!Broccoli = "A vegetable" Table!Pork = "A meat" Console.WriteLine(Table!Pork)
第二个例子完全等同于第一个例子,但是看起来好多了,至less在我眼中。 我发现那里有很多地方! 可以使用,特别是当涉及到XML和网页,那里只有吨的收集是按string索引。 一个不幸的局限是,这个事情跟着! 仍然必须是一个有效的标识符,所以如果你想用作密钥的string中有一些无效的标识字符,你不能使用! 运营商。 (例如,你不能说“Table!AB $ CD = 5”,因为$在标识符中是不合法的。)在VB6和之前,你可以使用括号来转义无效标识符(即“Table![AB $ CD]“),但是当我们开始使用括号来转义关键字时,我们失去了这样做的能力。 然而,在大多数情况下,这不是一个太大的限制。
为了获得真正的技术性,x!y在x有一个默认的属性将String或Object作为参数的情况下工作。 在这种情况下,x!y被改为x.DefaultProperty(“y”)。 有趣的一面是,在语言的词汇语法中有一个特殊的规则来使这一切工作。 那! 字符也被用作语言中的字符types,字符在操作符之前被使用。 所以没有特殊的规则,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
请参阅没有被过程调用修改的参数 – 底层variables
按名称传递参数,并重新sorting
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")
Using语句是VB 8以来的新特性,C#从一开始就具有它。 它调用为你自动处理。
例如
Using lockThis as New MyLocker(objToLock) End Using
Import aliases are also largely unknown:
Import winf = System.Windows.Forms ''Later Dim x as winf.Form
Consider the following event declaration
Public Event SomethingHappened As EventHandler
In C#, you can check for event subscribers by using the following syntax:
if(SomethingHappened != null) { ... }
However, the VB.NET compiler does not support this. It actually creates a hidden private member field which is not visible in 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
If you need a variable name to match that of a keyword, enclose it with brackets. Not nec. the best practice though – but it can be used wisely.
例如
Class CodeException Public [Error] as String ''... End Class ''later Dim e as new CodeException e.Error = "Invalid Syntax"
eg Example from comments(@Pondidum):
Class Timer Public Sub Start() ''... End Sub Public Sub [Stop]() ''... End Sub
There are a couple of answers about XML Literals, but not about this specific case:
You can use XML Literals to enclose string literals that would otherwise need to be escaped. String literals that contain double-quotes, for instance.
而不是这个:
Dim myString = _ "This string contains ""quotes"" and they're ugly."
你可以这样做:
Dim myString = _ <string>This string contains "quotes" and they're nice.</string>.Value
This is especially useful if you're testing a literal for CSV parsing:
Dim csvTestYuck = _ """Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA""" Dim csvTestMuchBetter = _ <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value
(You don't have to use the <string>
tag, of course; you can use any tag you like.)
DateTime can be initialized by surrounding your date with #
Dim independanceDay As DateTime = #7/4/1776#
You can also use type inference along with this syntax
Dim independanceDay = #7/4/1776#
That's a lot nicer than using the constructor
Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
You can have 2 lines of code in just one line. hence:
Dim x As New Something : x.CallAMethod
Optional Parameters
Optionals are so much easier than creating a new overloads, such as :
Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...") Console.Writeline(msg) ''//do stuff End Function
Title Case in VB.Net can be achieved by an old VB6 fxn:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Properties with parameters
I have been doing some C# programming, and discovered a feature that was missing that VB.Net had, but was not mentioned here.
An example of how to do this (as well as the c# limitation) can be seen at: Using the typical get set properties in C#… with parameters
I have excerpted the code from that answer:
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