【问题标题】:Handling Lots of Optional Parameters处理大量可选参数
【发布时间】:2016-04-05 16:44:23
【问题描述】:

我很不好意思分享这个功能,但我需要帮助来整理它。我很久以前写了这个,只是为了一个非常简单的用途,但它已经失控了,我不知道如何正确处理它。

Public Shared Function SetVariables(msg As String, Optional name As String = "", Optional target As String = "", Optional amount As Decimal = 0, Optional cost As String = "0", Optional keyword As String = "", Optional time As String = "", Optional reward As String = "", Optional participantList As String = "", Optional participantCount As Integer = 0, Optional game As String = "", Optional viewers As String = "", Optional followers As String = "", Optional link As String = "", Optional _options As String = "", Optional Year As String = "", Optional Month As String = "", Optional Day As String = "", Optional Hour As String = "", Optional Minute As String = "", Optional grpname As String = "")
    Dim balance As Decimal
    Dim holdings As Decimal
    If name > "" Then
        If Options.Accounts.ContainsKey(name) Then
            If Options.Holdings.ContainsKey(Options.Accounts.Item(name)) Then
                holdings = Options.Holdings.Item(Options.Accounts.Item(name))
            End If
            balance = Options.Accounts.Item(name).Points
        End If
    End If
    msg = msg.Replace("[name]", StrConv(name, VbStrConv.ProperCase))
    If holdings > 0 Then
        msg = msg.Replace("[balance]", balance & "[" & holdings & "]")
    Else
        msg = msg.Replace("[balance]", balance)
    End If
    msg = msg.Replace("[channel]", Subs.UppercaseFirstLetter(Options.Channel.TrimStart("#")))
    msg = msg.Replace("[target]", Subs.UppercaseFirstLetter(target))
    msg = msg.Replace("[amount]", amount)
    msg = msg.Replace("[cost]", cost)
    msg = msg.Replace("[keyword]", keyword)
    msg = msg.Replace("[time]", time)
    msg = msg.Replace("[reward]", reward)
    msg = msg.Replace("[participantList]", participantList)
    msg = msg.Replace("[participantCount]", participantCount)
    msg = msg.Replace("[botname]", Subs.UppercaseFirstLetter(Options.User))
    If msg.Contains("[groups]") Then msg = msg.Replace("[groups]", GetSortedGroups(name))
    If msg.Contains("[group]") Then msg = msg.Replace("[group]", GetSortedGroups(name, True))
    msg = msg.Replace("[game]", StrConv(game, VbStrConv.ProperCase))
    msg = msg.Replace("[viewers]", viewers)
    msg = msg.Replace("[followers]", followers)
    msg = msg.Replace("[link]", link)
    msg = msg.Replace("[options]", options.ToUpper)
    msg = msg.Replace("[years]", Year)
    msg = msg.Replace("[months]", Month)
    msg = msg.Replace("[days]", Day)
    msg = msg.Replace("[hours]", Hour)
    msg = msg.Replace("[minutes]", Minute)
    msg = msg.Replace("[grpname]", StrConv(grpname, VbStrConv.ProperCase))

    If balance = 1 Or amount = 1 Then
        msg = msg.Replace("[currency]", Options.PName)
    Else
        msg = msg.Replace("[currency]", Options.PNames)
    End If
    Return msg
End Function

基本上,我将一个字符串传递给这个函数,它包含其中的一些:[name] [keyword] 等,将被替换为其他内容。有时我还必须传递数据以替换那些数据,这就是问题开始的地方。我希望这些在同一个函数中,但我现在有很多参数。我从来没有在一次函数调用中使用所有这些参数,随着时间的推移,我会添加更多的参数。

关于如何更好地处理此类事情的任何建议?我应该把这个功能拆开并单独处理替换吗?

【问题讨论】:

  • 由这些参数组成的类应该更简洁
  • 你可能是对的。我实际上考虑过这样做,但后来忘记了这个想法。谢谢!
  • @Plutonix 使用我在我的 OP 中分享的内容,您能否编写一个粗略的示例来说明如何构建此类?使用这个类时,我仍然觉得我的字符串很长,但也许我看错了。
  • 好吧,如果它是我的代码,我会使用一个类,并且该过程将是其中的一个方法。如果可能的话,而不是将 msg 字符串破解为位,我会使用 StringBuilder 来构造它。不过我不知道其他一些方法是做什么的。
  • ...听起来你构建了传递给它的字符串,所以我会尝试从头开始构建它,而不是占位符 ([Name])。

标签: vb.net function optional-parameters


【解决方案1】:

您这样做的方式非常昂贵。 Strings 是不可变的,所以这样一行:

msg = msg.Replace("[followers]", followers)

...撕开原来的msg,然后从碎片和替换中创建一个新的。我已经用用户创建的短字符串来指定文本块的布局,但StringBuilder 在更长的字符串和/或大量替换上会更快、更有效。 This post is an extreme example 使用 1MB 字符串(SB 将时间从 5 分钟缩短到 86 毫秒)。

因为听起来您构建了被切碎的起始字符串,所以如果可能的话,我会尝试从头开始构建它并一路格式化。我对数据或其他一些方法知之甚少,但这应该会给你一个想法:

Public Class MessageMaker
    Public Property Name As String
    Public Property Target As String
    Public Property Amount As Nullable(Of Decimal)
    Public Property Cost As String          ' string? Really?

    ' illustration
    Public Property Participants As List(Of String)
    ' ergo participantCount==Participants.COunt()

    Public Property GroupName As String
    ' etc ad nauseum

    Public Sub New()
        Participants = New List(Of String)
    End Sub

    Public Function GetFormattedMsg() As String
        Dim sb As New StringBuilder

        sb.AppendFormat("The Name: {0}; ", Name)
        ' or...this will only append the name when lengh>0
        'sb.AppendFormat(If(String.IsNullOrEmpty(Name), "", TitleCase(Name) & "; "))

        If Amount.HasValue Then
            sb.AppendFormat("amt = {0}; ", Amount.Value.ToString("C2"))
        End If

        Dim p As String = ""
        If Participants.Count > 0 Then
            sb.AppendFormat("Participant Count: {0}; ", Participants.Count)
            ' convert names to TitleCase, sort
            p = String.Join(", ", Participants.OrderBy(Function(x) x).
                             Select(Function(j) TitleCase(j)))

            sb.AppendFormat("Participant Names: {0}; ", p)
        End If

        sb.Append(If(String.IsNullOrEmpty(GroupName), "",
                                   String.Format("Grp: {0}; ", TitleCase(GroupName))))

        Return sb.ToString

    End Function

    Private Function TitleCase(str As String) As String
        Return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower)
    End Function

End Class

注意AmountNullable(Of Decimal)(或者可以写成As Decimal?)。如果你想省略它,除非它被给出,你可以使用.HasValue 来确定。这可以防止误导性数字:Amount: 0 真的意味着 0 还是意味着它没有被指定。不要打扰Nullable<T>,除非这很重要。

GroupName 处理显示了如何有条件地添加文本。我还将老式的 StrConv 替换为 NET 方法。我不知道GetSortedGroups 做了什么,但如果您愿意,任何组列表都可以即时排序(如Participants 所示)。

取决于这个类还需要做什么,而不是方法,结果可能来自.ToString()

Public Overrides Function ToString() As String
    ' all the code
    Return msg
End Function

测试代码:

Dim mm As New MessageMaker
mm.Name = "April Gala Festival"
mm.Amount = 1.23D
mm.Participants = New List(Of String) From {"ziggy", "zOEy", "HOOveR", "josh"}

Dim msg = mm.GetFormattedMsg()
' or
Dim msg = mm.ToString()

结果:

“名称:April Gala Festival;amt = 1.23 美元;参与者人数:4;参与者姓名:Hoover、Josh、Ziggy、Zoey;”

我猜结果字符串有一些标题和分隔符。该方法在每个段或元素后使用"; "

【讨论】:

  • 我明白了。我想我知道我现在需要做什么。一如既往地无条件提供帮助。谢谢。
猜你喜欢
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 2017-01-14
  • 1970-01-01
  • 2011-03-23
  • 2018-02-03
  • 2010-12-04
  • 2018-01-25
相关资源
最近更新 更多