VB.NET的隐藏功能?


Answers:


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

9
如果希望捕获特定的SQLException,则很有用,例如说-2,如果我没有记错的话就是网络超时:捕获ex作为sqlException其中ex.code = -2
Pondidum

哇!我刚刚阅读了一下,并立即使用以简化我上周写的try / catch块。我从来没有新的存在。
约翰M甘特

1
+1这里的地方净CLR团队博客解释了为什么异常过滤器是有用的blogs.msdn.com/clrteam/archive/2009/02/05/...
MarkJ

5
这不仅是隐藏的,而且在C#中也不可用。
Cheeso

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

现在,将值分配给声明为的变量时Rule,IDE将提供IntelliSense可能的值列表RuleTemplates

/编辑:

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

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

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


有趣-可以举例说明食用时的外观吗?
Brian MacKay

看起来有人仍然可以通过直接调用Rule构造函数来创建自己的规则?如果是这样,并且您想停止此操作,是否可以在库中将构造函数声明为“ Friend”?
Joel Coehoorn

Joel,在我的示例代码中,我本质上不禁止这样做。相反,我为用户提供了一些通用规则,并允许创建自己的专用规则。您当然可以通过将构造函数标记为friend或使用与枚举相同的类(Rule而不是)来防止这种情况RuleTemplate
Konrad Rudolph

某处有隐藏的有用属性使用列表吗?面对这个问题似乎令人难以置信,但是我不确定在哪里使用它,或者在某些情况下它是否可以解决主要问题而又无法将泛型限制为枚举。
马斯洛(Maslow)

@Maslow:这里没有涉及属性。那是一个xml注释。
乔尔·科恩荷恩

49

您是否注意到“喜欢”比较运算符?

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

3
等等,什么?这对我来说是新的!嗯,这比使用VB.NET字符串操作的方法好得多:D
STW,2009年

.. !! 尽管我从事过多个vb.net项目,但我不知道!有趣的功能...
Meta-Knight

woooooooooooooooooooooooow!谢谢!太棒了!它也可以在ELinq和DLinq中使用吗?XLinq呢?
Shimmy Weitzhandler,2009年

@dotjoe嗯?这些问题没有什么“懒惰”的。
乔希·李

这是如何执行的,引擎盖下发生了什么?它是reg ex库的同义词吗?
brumScouse

48

类型定义

VB知道一种原始的typedefvia Import别名:

Imports S = System.String

Dim x As S = "Hello"

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

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

2
请举例说明在我的IDE中无法识别“导入”一词。
Shimmy Weitzhandler,2009年

5
Imports它应该是。;-)以某种方式,将近整整一年都未发现此错误(并获得28次投票)。
康拉德·鲁道夫

我一直想知道如何创建一个具有默认值的新“类型”!凉!
eidylon

3
进口,进口,进口,什么!嘘,您认为我们在投票之前先阅读了这些帖子!
MarkJ

在视觉工作室测试中使用Imports Assert = xUnit.Assert
xunit的

45

哦! 并且不要忘记XML文字

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

那就是我要说的。实际上,我已经将XML文字用于非预期的用途。我用它来生成Javascript ... swortham.blogspot.com/2009/03/vb-2008.html
史蒂夫·沃瑟姆

9
除其他外,您可以使用XML Literals避免丑陋的字符串转义,例如,当您使用本身包含双引号的字符串时。只要把字符串XML文本内,期权价值,是这样的: <string>This string contains "quotes" and it's OK.</string>.Value (我发现这个写在解析CSV文件,其中每一个领域是在引号测试时特别方便它将。不是一直好玩逃脱手工所有这些报价在我测试线。)
Ryan Lundy

2
@Kyralessa:+1,很好的评论。实际上,这也是指定多行字符串(拥抱SQL语句等)的好方法。
亨氏2009年

内联XML是有史以来最糟糕的VB.NET功能之一。未经证实的事实。
格兰特·托马斯

39

对象初始化也在那里!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

1
我简直不敢相信他们戴着花括号。我们已经有了With语句。.他们可能只是重用了该语法。
山姆·艾克斯

2
我知道,这只是向您显示路上没有警察...哈哈JK
Shimmy Weitzhandler 2009年

4
当所有的编译器作者都是C / C ++程序员时,会发生什么。他们不断将C语法移植到其他语言中,因为他们无法想到任何更好的方法。
RBarryYoung

38

DirectCast

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

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

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

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

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

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


1)我无法找到该指南的链接,但我发现Paul Vick对此表示赞同(VB团队首席开发人员):

在现实世界中,您几乎不会注意到它们之间的区别,因此您最好使用更灵活的转换运算符,例如CType,CInt等。


(Zack编辑:在此处了解更多信息:如何在VB.NET中进行投射?


我实际上更喜欢TryCast()。它不会抛出异常,如果强制转换失败,则只返回Nothing。如果您期望强制转换经常失败,则它比TypeOf x是T ... DirectCast(x,T)快,并且比DirectCast失败时捕获异常要快。
鲍勃·金

6
如果正确地将DirectCast()和TryCast()配对使用,则它们是无价的。如果要始终将要转换的对象作为目标类型,则应使用DirectCast()(如果不是,则将出现错误,这是一件好事,因为这是意外情况)。如果要投射的对象可能是目标类型,或者是几种目标类型,则应使用TryCast()。单独使用一个或另一个将导致额外的开销(如果x的类型为y,则directcast(x,y)效率低下)或避免有效的错误(对于对象应始终为目标类型的情况,请使用TryCast())
STW,2009年

Yoooder:100%正确。那时我没提起这个遗憾,TryCast因为我主要是因为普遍使用来挑骨头CType
康拉德·鲁道夫

@Maslow:当然不是,因为TryCast根据文档,Enums是值类型,并且仅适用于引用类型。
康拉德·鲁道夫

+1:嘿。我必须承认,我刚读了这篇文章,就想:“哦,是的,DirectCast,我怎么忘记了?” 然后我在下一行代码中使用了它(因为我真的不喜欢CType)。
RBarryYoung

37

If 条件合并运算符

我不知道您怎么称呼它,但是Iif([expression],[value如果为true],[value如果为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)

很好,我不知道!我昨天刚刚使用了IIF,所以我将重新审视该代码块。
肖恩·高夫

4
告诉VS 2005。并非我们所有人都能使用最新和最出色的软件。
Sam Erwin

3
@废话,废话。此方法是100%类型安全的,并且返回与其(第二个和第三个)参数相同类型的对象。此外,参数之间必须有一个扩大的转换,否则将出现编译错误,因为类型不匹配。
康拉德·鲁道夫

1
是的,它的IIf()类型不安全
Pondidum

2
@ Br.Bill实际上,它完全等同于C和Perl的:?运算符,而不仅仅是简化版本。
康拉德·鲁道夫

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

5
实际上,您错过了两对:a)使用“ Select Case True”来测试多个变量,b)使用“ Case A,B,...”形式,甚至c)将“:”应用于-将执行语句与条件子句对齐(尽管许多人不喜欢这样)。
RBarryYoung

6
请不要使用Select Case True。只需使用If语句。
Ryan Lundy

4
我发现Select Case True比大胆的ifelse陈述更容易阅读。
dwidel 2010年

麻烦的Select Case True是,它看起来好像在评估每个Case语句并为每个正确的语句运行代码。但实际上,它是一个一个地评估它们,并且只为一个运行代码,这是正确的。If在这方面,的语法更加清晰(If...Else If...Else If...Else)。
瑞安·伦迪

31

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

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

我只是不喜欢输入超出要求的数字!


但是它还会创建一些隐藏的错误,尤其是当您在With中使用With
Varun Mahajan

2
我什至不知道您可以在现有的With中放置新的With。太草率了!
鲍勃·金

2Bob:我建议这不是草率的。它只是一种需要谨慎使用的语言构造。要在连续的行中设置许多属性,这很好,但是在复杂的代码段中找到一个随机的.Foo,然后不得不搜索上述with语句x行并不是该功能的好用处。
克里斯·克里斯塔

2
希望C#有这个吗?还是我睡着了,在C#隐藏功能答案中是否已经...?;-)
peSHIr

1
@Boo:您是对的,但仍然无法将其添加到“监视”列表中,这仍然很烦人。
Meta-Knight 2009年

31

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

Microsoft.VisualBasic.FileIO.TextFieldParser

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


5
+1奇怪的是C#人士在没有考虑这一点的情况下运行到FileHelpers。我确定FileHelpers非常出色,但这是一个外部依赖关系。
MarkJ

@MarkJ我想这是因为无知
内森·库普

我用尽了全力以赴地搜索这个类,但从未尝试过,谢谢。
2011年


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


1
一种用法是保留一个计数器,该计数器在每次调用该方法时都会增加。如果该变量标记为“静态”,则不会在每次方法调用时重新初始化。它只会在第一次调用时初始化,此后将保留其值。
Ryan Lundy

这就是为什么静态类成员在VB.NET中被命名为“共享”的原因
Enrico Campidoglio,2009年

VB.NET中的静态形式比经典VB中的形式更糟糕。应尽可能避免静态变量。
山姆·艾克斯

6
@Boo-相当清扫。你的理由是什么?我认为静态变量很有用。
MarkJ

4
上面示例中使用的static允许唯一的封装形式:具有方法级范围的类级变量。没有它,您将必须创建一个类级别的变量,即使您仅在一种方法中使用它,任何类成员都可以访问该变量。
Ryan Lundy

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

1
当试图在一百万行代码中找到针头时,我很难学到这一点。常规与整数除法。好提示!
杰森·欧文

23

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

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

这太好了,每个vb.net家伙都应该知道“我的名称空间”中的内容,它非常有用。
博士 邪恶的

我的* FTW :)
博士 邪恶的

3
这很有用,但我讨厌这个笨拙的名字。让我想起了这个secretgeek.net/refactvb.asp
MarkJ

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

看起来很酷,但是如果我需要,我想我做错了;-)。似乎违反了KISS原则。
chrissie1

4
当您要确保每个接收器都收到事件时,即使一个或多个抛出异常,它确实非常有用。
乔纳森·艾伦,

另一个值(我刚刚在MSDN站点上阅读了它)是,如果您的类抛出很多事件,则可以强制它使用哈希表/字典作为容器,而不是为每个事件声明一个字段。 msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
torial

凉。我认为这是将C#和VB.NET分开的功能之一(就像一个可以,但是另一个没有语法)。很高兴至少知道我在这方面是错的。
peSHIr

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具有将String或Object作为参数的默认属性,则x!y可以工作。在这种情况下,x!y更改为x.DefaultProperty(“ y”)。一个有趣的旁注是,语言的词汇语法中有一个特殊的规则可以使所有这些工作。!字符也用作语言中的类型字符,并且类型字符在操作符之前被吃掉。因此,没有特殊规则,x!y将被扫描为“ x!y”而不是“ x!y”。幸运的是,由于该语言中没有位置连续两个标识符有效,因此我们引入了以下规则:是标识符的开始,我们考虑!成为操作员而不是键入字符。


11
那是我故意遗忘的那些功能之一。它节省了一些按键操作,但使我的代码突出显示和易读。 现在又忘记了...。现在
STW,2009年

3
有趣,但并不真正有用。VB团队是在处理这种事情,而不是添加诸如yield关键字之类的缺失功能吗?:P
Meta-Knight

5
此功能是从VB3(AFAIK)向后兼容实现的
Eduardo Molteni,2009年

1
那些实现键索引的类是否具有从其继承的公共接口?像IKeyed一样,用整数索引的容器实现IENumberable的方式吗?
马斯洛(Maslow)

2
此功能还适用于DataRows(即dr!ID),这在LINQ to DataSets中非常方便。
保罗

19

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

如:

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

End Sub

我非常确定您可以在C#中执行类似的操作。在VB.NET中,它只是强制执行,在C#中是可选的?
杰斯珀·布莱德·詹森

5
您还可以将sub设为私有,这是隐藏诸如对非通用弃用版本的调用之类的东西的好方法。
克雷格·吉德尼

3
这可能是一个好主意。最经典的示例是,如果您想要一个Public Close方法,该方法也可以作为IDisposable的Dispose实现。
MarkJ

1
如果您碰巧实现了两个共享方法名称的接口,这也非常有用。
埃里克·尼科尔森

我已经看到了,并且一直希望自己没有。不应该被允许。
FastAl

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

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


6
哦,我的天哪……这是一个了不起的功能,尽管我不认为如果我用别人的代码阅读它会做什么。如果您只需要知道它在做什么就可以对其进行评论,那么您最好将throwaway变量传递给它。
mattmc3 2010年

7
这实际上是使用括号的副作用-括号会创建内部内容的临时值,即使只是一项也是如此。这种效果在vb6中使我丧命-子调用没有接受parens,但是我来自C的本能地将parens放入。6.0爆炸了多个参数,但是对于一个参数subs,它高兴地传递了一个temp值,并拒绝了以纪念我'byref'。大约每3年发生一次,大约是我忘记上一次事件所花费的时间。
FastAl

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

哇,这太酷了!我在使用Web服务等时看到了这一点,但我不知道您可以使用任何普通方法来做到这一点。
RichC

2
当您遇到需要太多参数的方法时,绝对是一种非常方便的工具。我尝试命名每个参数,并将name:= value放在自己的行上。对于采用> 5(我的经验法则)参数的方法,它更加直观和简洁。
STW,2009年

对于Office自动化尤其有用,在Office自动化中,您必须处理带有数十个可选参数的方法。
MarkJ

1
还可以混合使用两种方法:首先按顺序指定所需的参数,然后切换到命名参数作为可选参数!
RBarryYoung

15

从VB 8开始,Using语句是新的。它会自动为您处理。

例如

Using lockThis as New MyLocker(objToLock)

End Using

23
值得注意的是(仅因为我至少忘记了两次),您可以让一个Using语句包装多个Disposable对象。语法是“将objA用作新对象,将objB用作新对象...。”比嵌套多个Using语句要干净得多。
STW,2009年

绝对是我的最爱之一。
山姆·艾克斯

14

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

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

1
我认为我们有相同的想法。
chrissie1

3
@Boo-这是一个简单的示例,其中导入别名并不有害。 stackoverflow.com/questions/92869/...
torial

好的-有一个明显的滥用途径,但是不管@torial的咆哮如何,这都是一个很棒的功能。每次包含System.Text.RegularExpressions时,我都有与“ Group”类发生名称冲突的风险,因为这是一个常见的类名称。别名使您不必完全限定模棱两可的类,这可以节省大量时间,并且在正确使用时实际上可以提高可读性。该功能很棒,但是您的特定示例确实招来了一些嘲笑-不好意思。
mattmc3 2010年

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


你为什么要这么做?我无法想象一个用例,在这种情况下您需要知道VB中事件的订阅者数量。
Konrad Rudolph

在某些情况下,如果引发事件并且没有处理程序,则C#会引发异常。VB.Net不会。因此需要检查。
Joel Coehoorn

2
我将其用于业务对象事件,该事件向订户提出了验证错误消息。我想检查事件是否正在处理,以便知道收到验证错误。否则,我有业务对象抛出异常。
Technobabble

2
此私有成员的另一个方便使用是获取事件的调用列表。我已经在几种情况下使用它以异步方式向所有调用方触发事件(防止监听器A在监听器B接收到事件之前修改该事件;它还防止监听器A延迟向监听器B的传递)。我在自定义数据同步方案以及API中使用了很多。
STW,2009年

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

我认为如果您不使用“ If”作为示例关键字,则该示例会更好。
肖恩·高夫

4
timer.Start和timer.Stop弹簧作为良好使用此示例
Pondidum

5
+1表示免责声明。有几个框架类需要对此进行正确解决,例如[Assembly]
STW

5
[Enum]是使用括号而不是关键字来使用类的另一个很好的例子。
Ryan Lundy

13

关于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

如果要测试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>标签;您可以使用任何喜欢的标签。)


3
<q>就像Perl / Ruby中的用法一样,将是一个很好的标记。无论如何,这是一个很好的习惯用法。喜欢!
康拉德·鲁道夫

真是个天才的想法。谢谢
Jeremy

12

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

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

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

Dim independanceDay = #7/4/1776#

这比使用构造函数好得多

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

6
如果您已
启用

12

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

Dim x As New Something : x.CallAMethod

哇...我认为这只有通过类和继承才能实现
Jason

别忘了Call (New Something).CallAMethod()
乔纳森·艾伦

这是MS-Basic在Apple上的保留权] [!在我的商店里,我会因为使用Gotos而被嘲笑:-/
FastAl

在大多数情况下,这是要避免的,但是我喜欢在情况很短的case语句中使用它,例如Case 4:x = 22
dwidel

11

可选参数

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

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

1
我不知道C#会得到它们。它们很好,但是您必须谨慎使用它们,在您确定C#不会使用该代码(因为它不支持它们)的地方。FxCop /代码分析将告诉您重载该方法。
STW,2009年

...我发现可选参数很有用,同时仍将它们排除在生产代码之外。我在自己的网站上写了一篇简短的文章:yoooder.com/wordpress/?p=62
STW,

2
嗯,我非常鄙视这件事……但是对办公室自动化很有用
dance2die

9

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

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

1
它也在textinfo类中。不知道其中包含什么名称空间。可能是system.text
Shawn

您最好是.NET语言中立者,并使用Globalization TextInfo类转换ToTitleCase。如果你曾经的代码需要转换到C#,你会有很多要求Microsoft.VisualBasic程序有点脏东西的
杰里米

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

这很有趣,但是我不确定在哪里有用。myObj.Something(“ abc”)看起来更像是您访问的是功能而不是属性。不知道这能买到什么。
mattmc3 2010年

我讨厌模棱两可。应该是什么 方法或属性。一些重构工具建议在某些情况下也创建它们,看起来他们甚至都不知道...
brumScouse 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.