VB.NET的隐藏功能?

Sea*_*ugh 121 vb.net hidden-features

我已经学习了很多浏览C#的隐藏功能,当我找不到类似于VB.NET的东西时,我感到很惊讶.

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

tor*_*ial 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
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望捕获特定的SQLException,请注意-2,如果我没记错的话是网络超时:Catch ex as sqlException,其中ex.code = -2 (9认同)
  • 这不仅隐藏了,而且在C#中也不可用. (5认同)

Kon*_*lph 82

自定义Enum小号

VB的一个真正隐藏的功能是completionlistXML文档标记,可用于创建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
Run Code Online (Sandbox Code Playgroud)

现在,在为声明为的变量赋值时Rule,IDE会提供可能值的IntelliSense列表RuleTemplates.

/编辑:

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

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

事实上,IntelliSense与使用时的完全相同Enum.


Par*_*rsa 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*"
Run Code Online (Sandbox Code Playgroud)

  • 等什么?这对我来说是新的!嗯,这比使用VB.NET字符串操作的替代方案要好得多:D (3认同)

Kon*_*lph 48

类型定义

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

Imports S = System.String

Dim x As S = "Hello"
Run Code Online (Sandbox Code Playgroud)

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

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
Run Code Online (Sandbox Code Playgroud)

  • 应该是"进口".;-)不知何故,这个错误已经未被发现(并获得了28个赞成票)近一整年. (5认同)
  • 进口,进口,进口,等等!Sheesh,你认为我们在推荐它们之前*阅读*这些帖子! (3认同)
  • 请举例说明我的IDE中无法识别导入这个词. (2认同)

Nes*_*cio 45

哦! 并且不要忘记XML Literals.

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>
Run Code Online (Sandbox Code Playgroud)

  • 除此之外,您可以使用XML Literals来绕过丑陋的字符串转义,例如,当您使用本身包含双引号的字符串时.只需将字符串放在XML Literal中并调用Value,就像这样:`<string>这个字符串包含"引号",它没关系.</ string> .Value`(我在编写解析CSV文件的测试时发现这个特别方便每个字段都在引号中.在我的测试行中手动逃避所有这些引号都不会很有趣.) (9认同)
  • @Kyralessa:+1,好评.实际上,它也是指定多行字符串(拥抱SQL语句等)的好方法. (2认同)

Nes*_*cio 39

对象初始化也在那里!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
Run Code Online (Sandbox Code Playgroud)

  • 当所有编译器编写者本身都是C/C++程序员时,会发生什么.他们不断将C语法滑入其他语言,因为他们无法想象任何更好的东西. (4认同)
  • 我知道,这只是为了告诉你路上没有警察......哈哈JK (2认同)

Kon*_*lph 38

DirectCast

DirectCast是一个奇迹.从表面上看,它的工作方式类似于CType操作符,因为它将对象从一种类型转换为另一种类型.但是,它的工作规则要严格得多.CType因此,实际行为通常是不透明的,并且根本不明显执行哪种转换.

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

  • 取消装箱值类型,和
  • 在类层次结构中向上转换.

任何其他强制转换都不起作用(例如,尝试将a取消映射Integer到a Double)并将导致编译时/运行时错误(取决于情况以及静态类型检查可以检测到的内容).因此DirectCast,我尽可能地使用,因为这最好地捕获了我的意图:根据情况,我要么取消已知类型的值或执行向上转换.故事结局.

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

为什么这是一个隐藏的功能?VB团队已经发布了一个指南1,它不鼓励使用DirectCast(即使它实际上更快!),以使代码更加统一.我认为这是一个不好的指导方针,应该予以逆转:只要有可能,DirectCast对更一般的CType运营商有利.它使代码更清晰.CType另一方面,只有在确实需要时才应该调用,即应该调用缩小CType运算符(参见运算符重载).


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

在现实世界中,你几乎不会注意到这种差异,所以你也可以选择CType,CInt等更灵活的转换运算符.


(Zack编辑:在这里了解更多:我应该如何使用VB.NET?)

  • 当正确使用时,DirectCast()和TryCast()非常有用.如果正在转换的对象*总是*预期是目标类型,则应该使用DirectCast()(如果它不是你会得到一个错误,这是一件好事,因为它是一个意想不到的情况).如果正在转换的对象*可能是目标类型或多个目标类型,则应使用TryCast().使用一个或另一个专门要么导致额外的开销(如typeof运算x是y,则directcast(X,Y)是无效的),或者避免有效的错误(使用TryCast()的情况下,对象应*总*是目标类型) (6认同)

Kon*_*lph 37

If 条件和合并运算符

我不知道你怎么称它为隐藏,但Iif([表达式],[值如果为真],[值如果为假])作为对象函数可以计数.

它不像被弃用那样隐藏!VB 9的If运算符要好得多,并且与C#的条件和合并运算符完全一样(取决于你想要的):

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

Dim hello As String = Nothing
Dim y = If(hello, "World")
Run Code Online (Sandbox Code Playgroud)

编辑以显示另一个例子:

这可以使用If(),但会引起异常IIf()

Dim x = If(b<>0,a/b,0)
Run Code Online (Sandbox Code Playgroud)

  • 告诉VS 2005.并非所有人都能与最新最好的人合作. (4认同)
  • @Slough,胡说八道.此方法是100%类型安全的,它返回与其(第二个和第三个)参数相同类型的对象.此外,参数之间必须有更大的转换,否则会出现编译错误,因为类型不匹配. (3认同)
  • @Br.Bill事实上,它与C和Perl的`:?`运算符完全等同*,它不仅仅是简化版本. (2认同)

tor*_*ial 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
Run Code Online (Sandbox Code Playgroud)

但还有更多......

你可以做范围:

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
Run Code Online (Sandbox Code Playgroud)

还有更多......

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

Select Case True
 Case a = b
    ''//Do X
 Case a = c
    ''//Do Y
 Case b = c
    ''//Do Z
 Case Else
   ''//Exception case
 End Select
Run Code Online (Sandbox Code Playgroud)

  • 请不要使用Select Case True.只需使用If语句. (6认同)
  • 实际上你错过了一对:a)使用"Select Case True"测试多个变量,b)使用"Case A,B,..."形式,甚至c)将":"应用于 - 使用条件子句对执行语句进行排队(尽管许多人不喜欢这样). (5认同)
  • 我发现Select Case True比一个巨大的ifelse语句更容易阅读. (4认同)

小智 31

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

With ReallyLongClassName
    .Property1 = Value1
    .Property2 = Value2
    ...
End With
Run Code Online (Sandbox Code Playgroud)

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

  • 我甚至不知道你可以在现有的With中加入新的With.那只是马虎! (2认同)
  • 希望C#有这个吗?或者我已经睡着了,而且已经在C#hidden-features答案中了......?;-) (2认同)

cjk*_*cjk 31

最好的CSV解析器:

Microsoft.VisualBasic.FileIO.TextFieldParser
Run Code Online (Sandbox Code Playgroud)

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

  • +1 C#人员如何在没有考虑到这一点的情况下运行FileHelpers,这很奇怪.我确信FileHelpers很棒,但它是一个外部依赖. (5认同)

Joe*_*orn 26

  • AndAlso/OrElse逻辑运算符

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


Joe*_*orn 25

方法中的静态成员.

例如:

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

    return pattern.Replace(input, "")
End Function
Run Code Online (Sandbox Code Playgroud)

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

另一个用途是保持"随机"的实例:

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

    Return r.Next()
End Function 
Run Code Online (Sandbox Code Playgroud)

此外,这与简单地将其声明为该类的共享成员不同; 以这种方式声明的项目也保证是线程安全的.在这种情况下无关紧要,因为表达式永远不会改变,但还有其他可能的改变.

  • @Boo - 这是非常彻底的.你的理由是什么?我认为静态变量很有用. (6认同)
  • 静态(如上例所示)允许使用独特形式的封装:具有方法级范围的类级变量.没有它,你必须创建一个类级别的变量,任何类成员都可以访问它,即使你只在一个方法中使用它. (4认同)

Shi*_*mmy 25

在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
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 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
Run Code Online (Sandbox Code Playgroud)

然后可以按以下方式测试:

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
Run Code Online (Sandbox Code Playgroud)

  • 当你想要确保每个接收器获得事件时,即使一个或多个抛出异常,它确实非常有用. (4认同)

spl*_*tne 23

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

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

  • 这有点有用,但我讨厌这个愚蠢的名字.让我想起了这个http://www.secretgeek.net/refactvb.asp (3认同)

tor*_*ial 21

我刚发现一篇文章谈到"!" 运算符,也称为"字典查找运算符".以下是http://panopticoncentral.net/articles/902.aspx文章的摘录

技术名称为!operator是"字典查找运算符".字典是由键而不是数字索引的任何集合类型,就像英语字典中的条目被您想要定义的单词索引的方式一样.字典类型最常见的示例是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"))
Run Code Online (Sandbox Code Playgroud)

的!运算符可用于从使用字符串索引其值的任何字典类型中查找值.之后的标识符!用作查找操作中的键.所以上面的代码可以写成:

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

第二个例子完全等同于第一个例子,但看起来好多了,至少在我看来.我发现有很多地方在那里!可以使用,尤其是涉及XML和Web时,其中只有大量的字符串索引的集合.一个不幸的限制是事后的事情!仍然必须是一个有效的标识符,所以如果你想用作一个键的字符串中有一些无效的标识符字符,你就不能使用!运营商.(例如,你不能说"Table!AB $ CD = 5",因为$在标识符中不合法.)在VB6及之前,你可以使用括号来转义无效的标识符(即"表![AB $] CD]"),但是当我们开始使用括号来转义关键字时,我们失去了这样做的能力.在多数情况下,

为了获得真正的技术,如果x具有将String或Object作为参数的默认属性,则x!y有效.在这种情况下,x!y变为x.DefaultProperty("y").一个有趣的旁注是语言的词汇语法中有一个特殊的规则,使这一切都有效.的!character也用作语言中的类型字符,类型字符在运算符之前被占用.因此,如果没有特殊规则,x!y将被扫描为"x!y"而不是"x!y".幸运的是,由于在一行中两个标识符有效的语言中没有位置,我们只介绍了如果下一个字符在!之后的规则!是标识符的开头,我们考虑一下!成为一个运营商而不是一个类型角色.

  • 这是我用过的故意忘记的功能之一.它节省了一些按键,但我的代码突出显示和可读性混乱.*再次忘记了....现在* (11认同)
  • 此功能用于向后兼容VB3(AFAIK) (5认同)
  • 有趣,但不是很有用.这是VB团队的工作方式,而不是像yield关键字那样添加缺少的功能吗?:P (3认同)
  • 此功能也适用于DataRows(即dr!ID),这在LINQ to DataSet中非常方便. (2认同)

tor*_*ial 19

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

如:

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

End Sub
Run Code Online (Sandbox Code Playgroud)

  • 不确定它是不是一个好主意......但它的功能:) (5认同)
  • 你也可以将sub设为私有,这是一种很好的方式来隐藏诸如调用非泛型弃用版本的接口之类的东西. (5认同)
  • 这可能是一个好主意.经典的例子是,如果你想要一个Public Close方法,它也可以作为IDisposable的Dispose实现. (3认同)

Chr*_*aas 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
Run Code Online (Sandbox Code Playgroud)

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

  • 这实际上是使用括号的副作用 - 括号创建内部的临时值,即使只有一个项目.这个效果在vb6中杀了我 - Sub调用没有拿到parens,但是我来自C本能地把parens放进去.6.0在多个参数上爆炸,但是对于一个参数subs,它很高兴地传递了一个临时值并且拒绝尊重我"按地址".发生在大约每3年一次,大约是我忘记最后一次事件的时间. (7认同)
  • 哦,我的天啊......这是一个了不起的功能,虽然如果我用其他人的代码阅读它,我不认为我知道它在做什么.如果你只是为了知道它在做什么而发表评论,那么你也可以将扔掉的变量改为传入. (6认同)

小智 16

按名称传递参数,然后重新排序

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

    'Do stuff

End function
Run Code Online (Sandbox Code Playgroud)

用法:

Module Module1

    Sub Main()

        MyFunc() 'No params specified

    End Sub

End Module
Run Code Online (Sandbox Code Playgroud)

也可以按任何顺序使用":="参数规范调用:

MyFunc(displayOrder:=10, msg:="mystring")
Run Code Online (Sandbox Code Playgroud)

  • 当你遇到一个带有太多参数的方法时,肯定是一个非常方便的工具.我尝试命名每个参数,并将名称:= value放在自己的行上.对于采用> 5(我的经验法则)参数的方法,它更直观,更干净. (2认同)

tor*_*ial 15

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

例如

Using lockThis as New MyLocker(objToLock)

End Using
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是(只因为我已经忘记了至少两次)你可以使用一个Using语句包装几个Disposable对象.语法是"使用objA作为新对象,objB作为新对象...."它比嵌套多个Using语句要简洁得多. (23认同)

tor*_*ial 14

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

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
Run Code Online (Sandbox Code Playgroud)

  • @Boo - 这是一个简单的例子,其中导入别名不是邪恶的.http://stackoverflow.com/questions/92869/nunit-vs-visual-studio-2008s-test-projects-for-unit-testing/547199#547199 (3认同)

tor*_*ial 14

如果需要变量名称以匹配关键字的名称,请用括号括起来.不是.虽然是最好的做法 - 但它可以明智地使用.

例如

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

''later
Dim e as new CodeException
e.Error = "Invalid Syntax"
Run Code Online (Sandbox Code Playgroud)

例如评论中的例子(@Pondidum):

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

Public Sub [Stop]()
''...
End Sub
Run Code Online (Sandbox Code Playgroud)

  • +1用免责声明指出它.有几个框架类需要这个才能正确解析,例如[Assembly] (5认同)
  • [Enum]是另一个很好的例子,你需要括号才能使用类而不是关键字. (5认同)
  • timer.Start和timer.Stop作为好用的例子 (4认同)

Tec*_*ble 14

请考虑以下事件声明

Public Event SomethingHappened As EventHandler
Run Code Online (Sandbox Code Playgroud)

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

if(SomethingHappened != null)
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

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

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If
Run Code Online (Sandbox Code Playgroud)

更多信息:

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

  • 我将此用于业务对象事件,该事件向订阅者发出验证错误消息.我想检查事件是否正在处理,以便我知道正在接收验证错误.否则,我让业务对象抛出异常. (2认同)
  • 此私有成员的另一个方便用途是获取Event的调用列表.我用它在若干情况下火在一个异步的方式向所有呼叫者的事件(防止收听者从之前监听器B接收它修改事件;还可以防止收听者从延迟递送到监听器B).我在自定义数据同步方案和API中都经常使用它. (2认同)

Rya*_*ndy 13

关于XML Literals有几个答案,但不是关于这个特定情况:

您可以使用XML Literals来包含原本需要转义的字符串文字.例如,包含双引号的字符串文字.

而不是这个:

Dim myString = _
    "This string contains ""quotes"" and they're ugly."
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

Dim myString = _
    <string>This string contains "quotes" and they're nice.</string>.Value
Run Code Online (Sandbox Code Playgroud)

如果您正在测试CSV解析的文字,这将特别有用:

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

Dim csvTestMuchBetter = _
    <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value
Run Code Online (Sandbox Code Playgroud)

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

  • `<q>`将是一个很好的标签,类似于Perl/Ruby中的用法.无论如何,这是一个非常好的习语.喜欢! (3认同)

Par*_*rsa 12

您可以在一行中拥有2行代码.因此:

Dim x As New Something : x.CallAMethod
Run Code Online (Sandbox Code Playgroud)


dan*_*ash 12

可以使用#围绕日期来初始化DateTime

Dim independanceDay As DateTime = #7/4/1776#
Run Code Online (Sandbox Code Playgroud)

您还可以使用类型推断和此语法

Dim independanceDay = #7/4/1776#
Run Code Online (Sandbox Code Playgroud)

这比使用构造函数好很多

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
Run Code Online (Sandbox Code Playgroud)

  • 如果您有Option Strict On,则不会 (6认同)

dr.*_*vil 11

可选参数

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

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

  • 啊,我这么鄙视......但对办公自动化很有用 (2认同)

tor*_*ial 9

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

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Run Code Online (Sandbox Code Playgroud)


tor*_*ial 9

带参数的属性

我一直在做一些C#编程,并发现了一个缺少VB.Net的功能,但这里没有提到.

可以在以下位置看到如何执行此操作的示例(以及c#限制):使用C#中的典型get set属性...带参数

我摘录了该答案的代码:

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

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

    End Set
End Property
Run Code Online (Sandbox Code Playgroud)


Joe*_*orn 9

使用语句堆叠/组合多个:

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
Run Code Online (Sandbox Code Playgroud)

公平地说,你也可以用C#来做.但很多人都不知道这两种语言.


You*_*sef 8

我发现其中一个非常有用且有助于解决许多错误的功能是将参数显式传递给函数,尤其是在使用可选项时.

这是一个例子:

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

然后你可以这样称呼它:

DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)
Run Code Online (Sandbox Code Playgroud)

这样更干净,没有bug,然后调用这个函数

DoSomething(1,true)
Run Code Online (Sandbox Code Playgroud)


Joe*_*orn 7

  • 导入其父级后,子命名空间在范围内.例如,不必导入System.IO或者说System.IO.File来使用File类,你可以说IO.File.这是一个简单的例子:有些地方的功能真的很方便,C#不会这样做.


Par*_*rsa 7

你可以在一行中有一个If.

If True Then DoSomething()
Run Code Online (Sandbox Code Playgroud)

  • 还有其他的. (2认同)

Shi*_*mmy 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
Run Code Online (Sandbox Code Playgroud)

看看Beth Massi的XML Literals Tips/Tricks.


Edu*_*eni 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
Run Code Online (Sandbox Code Playgroud)

最近在VbRad中查看


Rya*_*ndy 6

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

如果你不小心用分号结束你的VB行,因为你做了太多的C#,分号就会被自动删除.实际上不可能(至少在VS 2008中)不小心用分号结束VB行.试试吧!

(它并不完美;如果您在最终的班级名称中间输入分号,则不会自动填写班级名称.)


Par*_*rsa 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
Run Code Online (Sandbox Code Playgroud)


Par*_*rsa 5

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

  • 始终设置Option Explicit.您可以使用工具选项在所有新源文件中自动插入. (4认同)
  • 我相信它实际上是Option Strict,而不是Option Explicit,它会阻止你键入Dim i并获得Object类型.如果你真的想要一个对象,它会强制你输入As Object.即使使用Option Infer,也最好启用Option Strict(和Option Explicit). (3认同)

小智 5

选择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
Run Code Online (Sandbox Code Playgroud)

  • 那是令人厌恶的. (7认同)
  • 在C#中有一个转换,这是一种憎恶 (3认同)
  • 我无法理解是什么让人们认为"Select Case True"比普通的`If`更好.如果你像`if`那样使用它,只需将它设为`If`即可.为什么要混淆? (2认同)

Dan*_*n F 5

Parsa的答案类似,类似的运算符在简单的通配符之上有很多可以匹配的东西.在阅读MSDN doco时,我几乎摔倒在椅子上:-)


Shi*_*mmy 5

IIf(False, MsgBox("msg1"), MsgBox("msg2"))
Run Code Online (Sandbox Code Playgroud)

结果是什么?两个消息框!!!! 这种情况发生,因为IIf函数在到达函数时会计算两个参数.

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

If(False, MsgBox("msg1"), MsgBox("msg2"))
Run Code Online (Sandbox Code Playgroud)

将仅显示第二个msgbox.

一般情况下,我建议更换你的vb代码中的所有IIF,除非你想要它们两个项目:

Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())
Run Code Online (Sandbox Code Playgroud)

你可以确定两个值都已加载.


Shi*_*mmy 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
Run Code Online (Sandbox Code Playgroud)

  • 实际上,这是一个非常有用的事情.尝试输入:"Public Sub Stop"它不起作用,因为Stop是一个关键字.括号允许您使用Stop作为方法名称,因为它比其他名称更有意义. (2认同)

Mar*_*rén 5

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

Dim b(0 to 9) as byte 'Declares an array of 10 bytes
Run Code Online (Sandbox Code Playgroud)

它清楚地表明了数组的跨度.将它与等效物进行比较

Dim b(9) as byte 'Declares another array of 10 bytes
Run Code Online (Sandbox Code Playgroud)

即使你知道第二个例子由10个元素组成,它也感觉不太明显.而且我不记得我从程序员那里看到代码的次数,而不是写的

Dim b(10) as byte 'Declares another array of 10 bytes
Run Code Online (Sandbox Code Playgroud)

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

"0到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
Run Code Online (Sandbox Code Playgroud)

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

  • 事实上,Dim b(9)作为字节创建了一个包含10个位置的数组,这让我很生气.我理解为什么微软会这样做,但这并不意味着这是一个很好的决定(我说这是一个喜欢VB .NET的人).当然,它并不像它可能那么糟糕,因为对于大多数事情我无论如何都使用集合而不是数组. (2认同)

归档时间:

查看次数:

27099 次

最近记录:

13 年,8 月 前