有没有办法将 ParamArray 值作为 byRef 处理,以便可以更新它们?

发布于 2024-07-14 16:16:37 字数 1717 浏览 8 评论 0原文

听起来很简单,但它不起作用。 在此示例中,我想将 3 个字段的值设置为等于第 4 个字段。 我可以做这样的事情......

Dim str1 As String = "1"
Dim str2 As String = "2"
Dim str3 As String = "3"
Dim str4 As String = "4"

str2 = str1
str3 = str1
str4 = str1

但这有点罗嗦(是的,我知道,vb 在大多数情况下是罗嗦的)。 我想要有一些可以用来将其减少为单行调用的东西,所以我制作了这个扩展方法。

Module Module1

    Sub Main()

        Dim str1 As String = "1"
        Dim str2 As String = "2"
        Dim str3 As String = "3"
        Dim str4 As String = "4"

        Console.WriteLine("Extension method return value = {0}", str1.SetEqual(str2, str3, str4))
        Console.WriteLine("String 1 = {0}", str1)
        Console.WriteLine("String 2 = {0}", str2)
        Console.WriteLine("String 3 = {0}", str3)
        Console.WriteLine("String 4 = {0}", str4)

        Console.ReadKey()

    End Sub

    <System.Runtime.CompilerServices.Extension()> _
    Public Function SetEqual(Of T)(ByVal source As T, _
                                   ByVal ParamArray targets() As T) _
                                   As T

        For _index = 0 To targets.Length - 1
            targets(_index) = source
            Console.WriteLine("Target Value {0} = {1}", _index, targets(_index))
        Next

        Return source

    End Function

End Module

看起来很简单,对吧? 好吧,输出是这样的......

Target Value 0 = 1
Target Value 1 = 1
Target Value 2 = 1
Extension method return value = 1
String 1 = 1
String 2 = 2
String 3 = 3
String 4 = 4

参数数组中的值没有在返回中更新! 我期望现在所有的最终值都是“1”,就像它们在函数中一样。

有没有办法获得像这样的可更新的 ParamArray 集合? ParamArray 必须声明为 ByVal,但是对于像 String 这样的引用类型,难道不应该只制作指针的副本并允许我更改基础值吗?

有没有更好的方法来得到我想要的东西? (C# 不是一个选项)。

Sounds simple enough, but its not working. In this example, I want to set the values of 3 fields to equal a 4th. I could do something like this....

Dim str1 As String = "1"
Dim str2 As String = "2"
Dim str3 As String = "3"
Dim str4 As String = "4"

str2 = str1
str3 = str1
str4 = str1

... but that's kind of wordy (yeah, I know, vb is wordy in most cases). I would like to have something I can use to reduce this to a single line call, so I made this extension method.

Module Module1

    Sub Main()

        Dim str1 As String = "1"
        Dim str2 As String = "2"
        Dim str3 As String = "3"
        Dim str4 As String = "4"

        Console.WriteLine("Extension method return value = {0}", str1.SetEqual(str2, str3, str4))
        Console.WriteLine("String 1 = {0}", str1)
        Console.WriteLine("String 2 = {0}", str2)
        Console.WriteLine("String 3 = {0}", str3)
        Console.WriteLine("String 4 = {0}", str4)

        Console.ReadKey()

    End Sub

    <System.Runtime.CompilerServices.Extension()> _
    Public Function SetEqual(Of T)(ByVal source As T, _
                                   ByVal ParamArray targets() As T) _
                                   As T

        For _index = 0 To targets.Length - 1
            targets(_index) = source
            Console.WriteLine("Target Value {0} = {1}", _index, targets(_index))
        Next

        Return source

    End Function

End Module

Seems straightforward enough, right? Well, the output is this...

Target Value 0 = 1
Target Value 1 = 1
Target Value 2 = 1
Extension method return value = 1
String 1 = 1
String 2 = 2
String 3 = 3
String 4 = 4

Values in the param array did not get updated in the return! I was expecting to have all of the final values now be "1", like they are in the Function.

Is there any way to get an update-able ParamArray collection like this? ParamArray must be declared ByVal, but with a reference type like String, shouldn't that only make a copy of the pointer and allow me to change the underlying value?

Is there a better way to get what I want? (C# is not an option for this).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神也荒唐 2024-07-21 16:16:37

ParamArray 无法实现您想要做的事情。 当您调用 ParamArray 方法时,会在后台发生以下情况

  1. CLR 分配一个适当长度的数组
  2. 然后将值复制到数组中
  3. 数组向下传递到函数中

没有调用后操作将值从数组复制回并传递到传入的原始变量中。

让函数修改值并在调用站点看到它的唯一可靠方法是传递值 ByRef。 您可以使用一些魔法来拥有一组采用 ByRefs 的重载,手动转换为数组,然后复制回来。 但这是你能得到的最接近的结果。

What you're trying to do cannot be achieved with ParamArray. When you call a ParamArray method the following occurs under the hood

  1. CLR allocates an array of appropriate length
  2. The values are then copied into the array
  3. Array is passed down into the function

There is no post call operation that will copy the values back out of the array and into the original variables that were passed in.

The only reliable way to have the function modify a value and have it seen at the call site is to pass the value ByRef. You could do a bit of magic to have a set of overloads which take ByRefs, manually convert to an array and then does a copy back. But that's the closest you're going to get.

暖树树初阳… 2024-07-21 16:16:37

对于这个例子来说可能有点晚了(几乎 10 年前),但如果它有效的话可能会帮助其他人...

您不能将参数数组作为引用传递,但可以将数组作为引用传递。

将其更改为 ByRef删除 ParamArray

然后修改此行:

Console.WriteLine("Extension method return value = {0}", str1.SetEqual({str2, str3, str4}))

只需记下附加的“{”和“}”即可将字符串传递为Array 而不是 ParamArray

我在类中使用它来传递控件数组并且它有效(ParamArray 没有)所以我希望(无法在这里测试它)但它可能值得一试

Might be a bit late for case in point (almost 10 years ago) but might help someone else if it works...

You cannot pass parameter-array as reference, but you can pass an array as reference.

Change it to ByRef and remove ParamArray

Then modify this line:

Console.WriteLine("Extension method return value = {0}", str1.SetEqual({str2, str3, str4}))

Just take note of the additional "{" and "}" to pass strings as Array rather than ParamArray

I used this in a class to pass an array of controls and it worked (where ParamArray did not) so I'm hoping (cannot test it here) but it might be worth a shot

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文