传递HashSet<;字符串>;通过引用

本文关键字:引用 gt 字符串 lt 传递 HashSet | 更新日期: 2023-09-27 18:25:47

是否可以通过引用函数来传递HashSet?这是我当前的代码。

this.scrapeFriends(startUsers, userIDs, 100);

功能

private void scrapeFriends(StringCollection startUsers, ref HashSet<string> userIDs, int p)
{
    // Do something
}

如果我删除引用,它就起作用了。如果我添加它,它就不会编译。

传递HashSet<;字符串>;通过引用

您总是通过引用传递HashSet<T>,因为它是引用类型。

ref关键字用于通过引用传递变量

基本上:

  • 无论是否使用ref,都可以更改HashSet<T>的内容
  • 使用ref关键字,可以将HashSet<T>实例替换为不同的实例,并让调用代码注意到这一点(您正在修改传递给方法的变量)
  • 如果没有ref关键字,如果用不同的实例替换实例,则该更改仅在被调用的方法内部有效,调用它的代码仍然具有旧引用

代码不编译的原因是,如果您将方法的参数设置为ref参数,则还必须使用ref关键字来调用它,因此将调用代码更改为:

this.scrapeFriends(startUsers, ref userIDs, 100);
                               ^^^
                                |
                                +-- add this

为了进行编译,您需要在调用站点添加ref

this.scrapeFriends(startUsers, ref userIDs, 100);

但是我想问你为什么这么做?HashSet<T>是.Net中的引用类型,因此它的副本不会传递给每个函数。每个函数将引用相同的HashSet<T>实例(但通过引用的不同副本)。ref导致引用通过引用传递,这在这里几乎肯定不需要

在少数情况下,您需要通过引用传递可变引用类型(如HashSet<T>)。你确定这是其中之一吗?特别地,该方法可以在不使用ref的情况下向集合添加新项目。如果您想首先更改该点的设置,则只需要ref。你不太可能想要在这里。

代码不编译的原因是,对于ref参数,您还需要在调用站点指定ref

this.scrapeFriends(startUsers, ref userIDs, 100);

但正如我所说,你不太可能想要这个。

如其他答案中所述,为了确保代码可编译,您需要在调用站点添加ref,如下所示。

this.scrapeFriends(startUsers, ref userIDs, 100);

为了提供更多的上下文,HashSet是C#中的一个引用类型。当您将其传递给不带ref的方法时,会传递存储HashSet的内存位置的地址。这使您只能从HashSet中添加/删除元素。

但是,当您在调用方法时使用ref时,会传递存储变量的位置的内存地址。这允许您将变量指向一个新位置,即创建一个HashSet的新实例并对其进行操作。