121

我已经通过浏览C# 的隐藏特性学到了很多东西,当我找不到与 VB.NET 类似的东西时,我感到很惊讶。

那么它的一些隐藏或鲜为人知的功能是什么?

4

64 回答 64

128

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
于 2008-09-19T14:16:17.807 回答
82

定制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.

于 2008-09-19T14:22:32.113 回答
49

你注意到 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*"
于 2009-02-01T11:57:04.797 回答
48

类型定义

VB 知道一种原始的typedef通过Import别名:

Imports S = System.String

Dim x As S = "Hello"

这在与泛型类型结合使用时更有用:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
于 2008-09-19T14:40:02.523 回答
45

哦!并且不要忘记XML Literals

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>
于 2008-09-19T14:34:09.667 回答
39

对象初始化也在那里!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
于 2008-09-19T14:17:56.633 回答
38

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 中进行投射?

于 2008-09-19T16:06:08.713 回答
37

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)
于 2008-09-19T14:14:25.207 回答
32

这是一个不错的。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
于 2008-12-26T19:59:06.013 回答
31

我一直使用的一个主要的省时方法是With关键字:

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

我只是不喜欢打字超过我必须的!

于 2008-09-19T14:10:48.723 回答
31

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

Microsoft.VisualBasic.FileIO.TextFieldParser

通过添加对 Microsoft.VisualBasic 的引用,这可以在任何其他 .Net 语言中使用,例如 C#

于 2009-06-02T16:13:53.457 回答
26
  • AndAlso/OrElse 逻辑运算符

(编辑:在此处了解更多信息:我应该始终使用 AndAlso 和 OrElse 运算符吗?

于 2008-09-19T14:10:43.263 回答
25

方法中的静态成员。

例如:

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 成员不同;以这种方式声明的项目也保证是线程安全的。在这种情况下这无关紧要,因为表达式永远不会改变,但在其他情况下它可能会改变。

于 2008-10-03T16:49:54.233 回答
25

在 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
于 2009-07-13T15:44:40.117 回答
23

自定义事件

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

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
于 2008-09-19T17:20:29.190 回答
23

我非常喜欢Visual Basic 2005 中引入的“My”命名空间。My多组信息和功能的快捷方式。它提供对以下类型信息的快速直观的访问:

  • My.Computer:访问与计算机相关的信息,例如文件系统、网络、设备、系统信息等。它提供对许多非常重要的资源的访问,包括 My.Computer.Network、My.Computer.FileSystem 和 My .计算机.打印机。
  • My.Application:访问与特定应用程序相关的信息,例如名称、版本、当前目录等。
  • My.User:访问与当前经过身份验证的用户相关的信息。
  • My.Resources:以强类型方式访问驻留在资源文件中的应用程序使用的资源。
  • My.Settings:以强类型方式访问应用程序的配置设置。
于 2008-10-10T11:13:39.103 回答
21

我刚刚发现一篇关于“!”的文章。运算符,也称为“字典查找运算符”。以下是文章摘录: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”。幸运的是,由于语言中没有连续两个标识符有效的地方,我们只是引入了规则,如果 ! 之后的下一个字符 是标识符的开始,我们考虑!成为运算符而不是类型字符。

于 2009-03-14T16:22:55.517 回答
19

这是内置的,与 C# 相比具有明显优势。无需使用相同名称即可实现接口方法的能力。

如:

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

End Sub
于 2008-09-19T14:28:48.713 回答
17

强制 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

请参阅过程调用未修改参数 - 基础变量

于 2010-05-14T20:45:28.817 回答
16

按名称传递参数,并重新排序它们

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")
于 2008-12-03T16:03:22.777 回答
15

从 VB 8 开始,Using 语句是新的,C# 从一开始就有它。它会自动为您调用 dispose。

例如

Using lockThis as New MyLocker(objToLock)

End Using
于 2008-09-19T14:24:00.877 回答
14

导入别名在很大程度上也是未知的:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
于 2008-09-19T14:22:04.783 回答
14

如果您需要一个变量名称来匹配关键字的名称,请用括号括起来。不是。虽然是最佳实践 - 但可以明智地使用它。

例如

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
于 2008-09-19T14:48:10.663 回答
14

考虑以下事件声明

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

于 2008-09-19T16:44:56.187 回答
13

关于 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>标签;您可以使用任何您喜欢的标签。)

于 2009-12-17T22:50:43.103 回答
12

您可以在一行中包含 2 行代码。因此:

Dim x As New Something : x.CallAMethod
于 2009-02-01T11:45:57.707 回答
12

DateTime 可以通过用 # 包围您的日期来初始化

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

您还可以将类型推断与此语法一起使用

Dim independanceDay = #7/4/1776#

这比使用构造函数要好得多

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
于 2009-06-29T14:51:37.937 回答
11

可选参数

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

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function
于 2008-11-27T16:24:49.410 回答
9

带参数的属性

我一直在做一些 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
于 2008-12-19T15:41:46.067 回答
9

VB.Net 中的标题案例可以通过旧的 VB6 fxn 实现:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
于 2008-09-19T14:51:41.870 回答
9

将多个 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# 中做到这一点。但是很多人在这两种语言中都不知道这一点。

于 2009-06-02T15:09:03.387 回答
8

我发现真正有用并有助于解决许多错误的功能之一是显式地将参数传递给函数,尤其是在使用可选时。

这是一个例子:

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)
于 2009-07-30T15:50:54.053 回答
7
  • 子命名空间在导入其父命名空间后在范围内。例如,不必导入 System.IO 或说 System.IO.File 来使用 File 类,您可以只说 IO.File。这是一个简单的例子:有些地方该功能真正派上用场,而 C# 没有做到这一点。
于 2008-09-19T14:13:39.200 回答
7

您可以在一行中有一个 If。

If True Then DoSomething()
于 2009-02-01T11:49:13.987 回答
7

如果您不知道以下内容,您真的不会相信这是真的,这确实是 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

于 2009-07-13T16:04:35.770 回答
7

使用 When 改进错误处理

注意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中查看

于 2009-09-18T18:31:15.537 回答
6

这是一个我没见过的有趣的;我知道它至少在 VS 2008 中有效:

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

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

于 2009-12-02T21:56:40.023 回答
6

breakVB 中的 C 语言不同,您可以ExitContinue您想要的块:

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
于 2010-11-05T12:06:22.577 回答
5

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
于 2009-05-19T18:57:57.000 回答
5

在 VB8 及以前的版本中,如果您没有为您引入的变量指定任何类型,则会自动检测 Object 类型。在 VB9 (2008) 中,如果 Option Infer 设置为 On(默认情况下) ,则Dim将像 C# 的关键字一样var

于 2009-02-01T12:03:53.210 回答
5

Parsa 的答案类似,除了简单的通配符之外,like 运算符还有很多可以匹配的东西。阅读 MSDN 文档时,我差点从椅子上摔下来 :-)

于 2009-06-22T15:02:13.303 回答
5
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())

您可以确定这两个值都已加载。

于 2009-07-13T16:30:44.783 回答
5

如果用 [ 和 ] 将名称括起来,则可以对属性和变量名称使用保留关键字

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
于 2009-07-13T16:34:54.883 回答
5

在 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

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

于 2009-10-23T11:17:01.627 回答
4

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

Private obj As MyProject.MyNamespace.MyClass

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

于 2008-09-19T14:26:38.453 回答
4

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

于 2009-03-28T12:18:41.010 回答
4

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
于 2009-08-18T21:24:50.610 回答
4

可能这个链接应该有帮助

http://blogs.msdn.com/vbteam/archive/2007/11/20/hidden-gems-in-visual-basic-2008-amanda-silver.aspx

于 2008-10-13T16:12:36.927 回答
4

与 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
于 2009-07-13T16:22:48.747 回答
3

别名命名空间

Imports Lan = Langauge

虽然不是 VB.Net 独有的,但在遇到命名空间冲突时经常会被遗忘。

于 2008-09-19T14:26:17.050 回答
3

VB 还提供了 OnError 语句。但是这些天它并没有多大用处。

On Error Resume Next
' Or'
On Error GoTo someline

于 2009-02-01T11:50:58.400 回答
2

我不知道你会说它有多隐蔽,但If接线员可以数数。

在某种程度上,它与许多类 C 语言中的?:(三元)或运算符非常相似。??但是,重要的是要注意它确实评估了所有参数,因此重要的是不要传递任何可能导致异常(除非你想要它)或任何可能导致意外副作用的东西。

用法:

Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
于 2008-09-19T14:10:56.743 回答
2
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# 中永远无法做到的事情:

  1. 处理 Button1.Click - 将处理程序附加到外部事件!
  2. VB 的隐含性允许您将处理程序的第一个参数声明为扩展类型。在 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
于 2009-07-14T08:57:12.770 回答
2

在 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

请在 Microsoft Connect 投票支持此功能

于 2009-02-01T11:35:24.890 回答
2

您可以使用 REM 注释掉一行而不是 ' 。不是超级有用,但可以帮助重要的评论脱颖而出,而无需使用“!!!!!!!!!” 管他呢。

于 2008-09-19T14:44:50.110 回答
2

可空日期!这在您有数据输入/输出数据库(在本例中为 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
于 2010-10-14T16:25:55.960 回答
1

Documentation of code

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
于 2011-04-01T02:17:17.120 回答
1

我以前很喜欢可选的函数参数,但现在我用得更少了,因为我经常在 C# 和 VB 之间来回穿梭。C# 什么时候支持它们?C++ 甚至 C 都有它们(某种意义上的)!

于 2008-09-19T14:19:08.940 回答
1

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

于 2009-02-01T12:01:19.953 回答
1

ByValByRef关键字的区别:

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
于 2009-07-14T10:12:07.093 回答
0
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
于 2009-07-13T16:19:20.860 回答
0

又是可选参数!

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

' Call
DoSmtg(,,"c argument")

DoSmtg(,"b argument")
于 2011-05-09T20:24:35.510 回答
0

方法的属性!例如,在设计时不应该可用的属性可以是 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()如果您进行任何数量的调试,放入也非常有帮助(请注意,您仍然可以在函数或其他任何内容中放置断点,但您不能单步执行该函数)。

此外,将事物分类(例如,“数据”)的能力意味着,如果您确实希望该属性显示在属性工具窗口中,则该特定属性将显示在该类别中。

于 2010-10-14T15:12:51.283 回答
-3

我的关键字

“我”关键字在 VB.Net 中是独一无二的。我知道这很常见,但是“Me”和 C# 等效的“this”之间是有区别的。区别在于“this”是只读的,而“Me”不是。这在你有一个变量实例的构造函数中很有价值,你希望该变量已经被构造为相等,因为你可以设置“Me = TheVariable”,而不是在 C# 中你必须手动复制变量的每个字段(其中如果有很多字段并且容易出错,那可能会很糟糕)。C# 的解决方法是在构造函数之外进行赋值。这意味着你现在如果对象是自构造成一个完整的对象,你现在需要另一个函数。

于 2010-06-03T20:02:18.367 回答