VB.NET的隐藏功能?

时间:2020-03-06 14:26:06  来源:igfitidea点击:

通过隐藏功能,我学到了很多东西
当我找不到东西时,坎德的丈夫感到惊讶
与VB.NET类似。

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

解决方案

  • AndAlso / OrElse逻辑运算符

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

我一直使用的主要省时工具是With关键字:

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#却没有。

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")

编辑以显示另一个示例:

这将与If()一起使用,但会导致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}

我曾经非常喜欢可选的函数参数,但是现在我不得不在Cand VB之间来回很多,因此我很少使用它们。什么时候支持他们? C ++甚至C都有(某种)!

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

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

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将提供" RuleTemplates"中可能值的IntelliSense列表。

/编辑:

由于此功能依赖于IDE,因此很难显示使用时的外观,但我只使用屏幕截图:

运行中的完成列表http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

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

从VB 8开始,using语句是新的。它会自动为我们处理。

例如。

Using lockThis as New MyLocker(objToLock)

End Using

混叠名称空间

Imports Lan = Langauge

尽管不是VB.Net特有的,但在遇到名称空间冲突时通常会忘记它。

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

Private obj As MyProject.MyNamespace.MyClass

要更改根名称空间,请使用"项目"->"属性"菜单选项。根名称空间也可以清除,这意味着所有名称空间块都将成为其所包含代码的根级别。

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

如:

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

End Sub

哦!并且不要忘记XML文字。

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

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

Imports S = System.String

Dim x As S = "Hello"

与泛型类型结合使用时,这将更为有用:

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

我们可以使用REM注释掉一行,而不是"

。并不是超级有用,但是可以使用" !!!!!!!"来帮助重要的注释脱颖而出。管他呢。

如果我们需要一个变量名来与关键字匹配,请将其括在方括号中。不需要。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。虽然是最佳做法,但可以明智地使用它。

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

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

例如

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

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

例如评论示例(@Pondidum):

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

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

DirectCast是一个奇迹。从表面上看,它与CType运算符的相似之处在于它将对象从一种类型转换为另一种类型。但是,它按照更严格的规则集工作。因此,CType的实际行为通常是不透明的,完全不知道执行哪种转换。

  • 取消装箱值类型,以及
  • 在类层次结构中转换。

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

任何其他强制转换都将不起作用(例如,尝试将"整数"解包为"双精度"),并会导致编译时/运行时错误(取决于情况以及通过静态类型检查可以检测到的内容)。因此,我尽可能使用DirectCast,因为这最能体现我的意图:根据情况,我或者想取消已知类型的值装箱,或者执行向上转换。故事结局。

另一方面,使用CType会使代码的读者想知道程序员的真正意图,因为它可以解决各种不同的操作,包括调用用户定义的代码。

为什么这是隐藏功能? VB团队发布了一个指南1,该指南不鼓励使用DirectCast(即使实际上更快!),以使代码更加统一。我认为这是一个错误的指导原则,应予以扭转:只要有可能,就应将DirectCast优先于更通用的CType运算符。它使代码更加清晰。另一方面,只有在确实有此意图时才应调用CType,即应调用缩窄的CType运算符(请参阅运算符重载)。

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.

1)我无法找到该指南的链接,但我发现Paul Vick对此持反对态度(VB团队首席开发人员):

(由Zack编辑:在此处了解更多:我应该如何在VB.NET中进行投射?)

Public Event SomethingHappened As EventHandler

考虑以下事件声明

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

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

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

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

更多信息:

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

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

我真的很喜欢Visual Basic 2005中引入的"我的"命名空间。我是几组信息和功能的捷径。它提供了对以下类型信息的快速直观访问:

也许这个链接应该有所帮助

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

可选参数

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#...中的典型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

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

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

不可能在VB中明确实现接口成员,但是可以使用其他名称来实现它们。

请在Microsoft Connect上对此功能进行投票。

Dim x As New Something : x.CallAMethod

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

If True Then DoSomething()

我们可以在一行中包含一个If。

On Error Resume Next
' Or'
On Error GoTo someline

VB还提供了OnError语句。但这几天用处不大。
`

`

我们是否注意到"喜欢"比较运算符?

Dim b As Boolean =" file.txt"类似于" * .txt"

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*"

来自MSDN的更多信息

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

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

The technical name for the ! operator
  is the "dictionary lookup operator." A
  dictionary is any collection type that
  is indexed by a key rather than a
  number, just like the way that the
  entries in an English dictionary are
  indexed by the word you want the
  definition of. The most common example
  of a dictionary type is the
  System.Collections.Hashtable, which
  allows you to add (key, value) pairs
  into the hashtable and then retrieve
  values using the keys. For example,
  the following code adds three entries
  to a hashtable, and looks one of them
  up using the key "Pork".
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
  values from any dictionary type that
  indexes its values using strings. The
  identifier after the ! is used as the
  key in the lookup operation. So the
  above code could instead have been
  written:
Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)
The second example is completely
  equivalent to the first, but just
  looks a lot nicer, at least to my
  eyes. I find that there are a lot of
  places where ! can be used, especially
  when it comes to XML and the web,
  where there are just tons of
  collections that are indexed by
  string. One unfortunate limitation is
  that the thing following the ! still
  has to be a valid identifier, so if
  the string you want to use as a key
  has some invalid identifier character
  in it, you can't use the ! operator.
  (You can't, for example, say
  "Table!AB$CD = 5" because $ isn't
  legal in identifiers.) In VB6 and
  before, you could use brackets to
  escape invalid identifiers (i.e.
  "Table![AB$CD]"), but when we started
  using brackets to escape keywords, we
  lost the ability to do that. In most
  cases, however, this isn't too much of
  a limitation.
  
  To get really technical, x!y works if
  x has a default property that takes a
  String or Object as a parameter. In
  that case, x!y is changed into
  x.DefaultProperty("y"). An interesting
  side note is that there is a special
  rule in the lexical grammar of the
  language to make this all work. The !
  character is also used as a type
  character in the language, and type
  characters are eaten before operators.
  So without a special rule, x!y would
  be scanned as "x! y" instead of "x !
  y". Fortunately, since there is no
  place in the language where two
  identifiers in a row are valid, we
  just introduced the rule that if the
  next character after the ! is the
  start of an identifier, we consider
  the ! to be an operator and not a type
  character.

我刚刚找到一篇有关"!"的文章。运算符,也称为"字典查找运算符"。这是该文章的摘录:http://panopticoncentral.net/articles/902.aspx

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

选择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

在此示例中假设简单的几何对象:

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

将多个using语句堆叠/分组在一起:

公平地说,我们也可以使用C#来实现。但是很多人都不知道这两种语言。

Microsoft.VisualBasic.FileIO.TextFieldParser

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

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

与Parsa的答案类似,like运算符在简单的通配符之上可以匹配很多东西。在阅读有关MSDN doco的文章时,我差点摔倒椅子了:-)

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

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

Dim independanceDay = #7/4/1776#

我们还可以在此语法中使用类型推断

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

比使用构造函数好得多

在vb中,这些运算符之间存在差异:

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

/Double
\Integer,忽略余数

如果我们不了解以下内容,那么我们真的不会相信这是真的,这确实是Clack的重要时光:

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

(这称为XML文字)

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

看看Beth Massi撰写的XML Literals Tips / Tricks。

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#不同,在VB中,我们可以依赖非空项目的默认值:

int x;
var y = x.ToString(); //Use of unassigned value

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

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

结果是什么?两个消息框!!!
发生这种情况是因为IIf函数在到达函数时会同时评估两个参数。

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

VB有一个新的If运算符(就像C ?:运算符一样):

将仅显示第二个msgbox。

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

通常,我建议我们替换vb代码中的所有IIF,除非我们希望它能够同时体现这两个方面:

我们可以确定两个值都已加载。

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

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

  • 处理Button1.Click-在外部​​将处理程序添加到事件!
  • VB的隐式性允许我们将处理程序的第一个参数声明为扩展类型。在C#中,即使是预期的类型,也无法将委托寻址到其他模式。

在此代码段中,我们有2件事(也许还有更多?),我们在C#中无法做到:

同样,在C中,我们无法对C中的对象使用预期的功能,因此我们可以梦dream以求(现在,他们已经创建了dynamic关键字,但它与VB相距甚远)。
在C#中,如果我们要编写(new object())。Enabled,则会收到一个错误,指出类型object没有方法" Enabled"。
现在,我不是一个会建议我们是否安全的人,该信息按原样提供,我们可以自己做,还是静止不动,有时(例如使用COM对象时)这是一件好事。
当期望值肯定是一个按钮时,我个人总是写(作为按钮发送)。

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

实际上:再举个例子:

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

ByVal和ByRef关键字之间的区别:

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

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)

这样会更清洁,更没有错误,然后像这样调用该函数

'''<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改​​进错误处理

根据上下文,关键字Nothing可以表示default(T)或者null。我们可以利用此方法创建一个非常有趣的方法:

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

注意在尝试<3时,在Catch ex As IO.FileLoadException'行中使用when`。

最近在VbRad中查看

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

在vb.net中声明数组时,请始终使用" 0到xx"语法。

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

这使数组范围变得非常清楚。与同等的比较

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

即使我们知道第二个示例包含10个元素,也不会感到显而易见。而且我记不清有多少次看到来自程序员的代码,他们想要上面的代码而写了

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

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

" 0到xx"语法也适用于以下情况

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

这是一个我从未见过的有趣的东西。我知道它至少可以在VS 2008中使用:

如果由于使用C#过多而意外地以分号结束VB行,则会自动删除分号。实际上(至少在VS 2008中也是)无意地用分号结束VB行是不可能的。试试吧!

(这并不完美;如果我们在最终班级名称的中间输入分号,则不会自动完成班级名称。)

关于XML文字有几个答案,但是关于这种特定情况没有答案:

我们可以使用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

你可以这样做:

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

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

如果我们要测试文字以进行CSV解析,这将特别有用:

(当然,我们不必使用&lt;string>标签;我们可以使用任何喜欢的标签。)

强制ByVal

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

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

请参见过程调用底层变量未修改参数

我的关键字

"我"关键字在VB.Net中是唯一的。我知道这很普遍,但是" Me"和流行的" this"之间是有区别的。区别是" this"是只读的," Me"不是。这在构造函数中非常有用,在该构造函数中,我们有一个变量实例,我们希望该变量已被构造为相等,因为我们只需设置" Me = TheVariable"即可,而C语言则需要我们手动复制变量的每个字段(如果有很多字段并且容易出错,那就太可怕了。解决方法是在构造函数外部进行赋值。这意味着我们现在如果该对象正在自我构建为一个完整的对象,则现在需要另一个功能。

<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

方法的属性!例如,在设计时不应该使用的属性可以是:1)从属性窗口中隐藏,2)未序列化(特别是烦人的用户控件或者从数据库加载的控件):

如果我们进行任何数量的调试,则放入DebuggerStepThrough()也非常有帮助(请注意,我们仍然可以在函数中或者其他任何东西中放置一个断点,但不能单步执行该函数)。

同样,能够将内容归类(例如"数据")意味着,如果我们确实希望该属性显示在属性工具窗口中,则该特定属性将显示在该类别中。

<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

空的日期!在我们有数据要进出数据库(在本例中为MSSQL Server)的情况下,此功能特别有用。我有两个过程可为我提供一个SmallDateTime参数,并填充一个值。其中一个采用简单的旧日期并进行测试以查看其中是否有任何值,并指定一个默认日期。另一个版本接受Nullable(Of Date),因此我可以使日期保持无值状态,接受存储过程中的默认值

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

段落数量不匹配