作为可选参数传递以使子例程像被省略一样工作的优雅方法?

Elegant way to pass as an optional parameter to make the subroutine work as if it was omitted?

在VB6中,函数Mid(string, start, [length])有一个可选参数length。如果省略,将传递 start 边界后的整个字符。

假设我只希望在特定条件下使用此默认行为:

s = Mid(s, i, IIf(condition, j, TheValue)) ' What could be TheValue?

由于lengthVariant类型,所以我试了Empty。它没有用。 -1Nothing 也没有。 我不想在 If-Then-Else 子句或其他方式中复制到 Mid 调用。这可能吗?

在 c++ 中,std::string 这些可选参数在默认效果为零位置或长度时用 0 表示,在“无限”长度时用 std::string::npos 表示。您可以显式提供该值并获得相同的行为。

我不知道 m/s 字符串中的等价常量是什么[实际上它是一个不同的函数定义,所以没有]。另一种方法是传入字符串长度,因为这是当前可能的最长长度。

?: 三元运算符是一种呈现 2 个值的简单方法,并且可以在它们之间进行选择。

您可以定义自己的 Mid 函数:

Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer = -1) As String
    If p_iLength < 0 Then
        Mid = VBA.Mid(p_sString, p_iStart)
    Else
        Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
    End If
End Function

这应该适用于您问题中的代码,使用 -1(或任何负整数)作为 TheValue

不存在这样的值。当您省略长度参数时,编译器会通过 VBRT 选择不同的路径——它会生成不同的代码。如果你想模仿它,你需要做同样的事情,使用 If-Else 或类似的结构来处理这两种情况,比如@ÉtienneLaneville suggests

作为@Étienne 解决方案的替代方案,VB 提供了 IsMissing 方法:

Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer) As String
    If IsMissing(p_iLength) Then
        Mid = VBA.Mid(p_sString, p_iStart)
    Else
        Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
    End If
End Function

作为这个包装方法 returns 一个字符串,我建议使用 MidString 版本,即 Mid$。后者比 Variant 版本 (Mid)

稍快

这在 this site 中得到了很好的解释,但在发帖时,请求超时。不确定是永远消失了还是只是暂时的问题。

这是 OP 的 s = Mid(s, i, IIf(condition, j, TheValue))

的工作示例
Option Explicit

Property Get TheValue(Optional RetVal As Variant)
    TheValue = RetVal
End Property

Private Sub Form_Load()
    Dim s As String
    Dim i As Long
    Dim j As Long
    Dim condition As Boolean
    
    s = "test test test"
    i = 6: j = 3
    condition = False
    s = Mid(s, i, IIf(condition, j, TheValue))         '<--- this works!
    Debug.Print s
End Sub

请注意 TheValue returns 如何“缺失”VariantIsMissing 测试呈阳性并且可以用来代替可选参数而不是不传递实参.