C#是按引用还是按值返回?

6
在下面的场景中,“Pool”会被按值还是按引用返回?
private static List<Item> Pool;

public static List<Item> GetPool()
{
    return Pool;
}

我希望能实现在请求时循环遍历列表的能力(以便另一个线程可以添加/删除列表项,但调用线程的列表保持不变,从而foreach循环不会导致异常)。如果返回值,则它将是自己的列表,而如果是引用,则仍然存在列表被修改的危险。如果我有任何错误,请纠正我,这只是我的理解。

3
为什么不设置一个测试场景,然后在调试器中进行检查以找出答案呢?根据你发布的这5行代码,我认为你已经完成了可行的50%测试设置。 - abelenky
1
为什么不看一下 .net 4.0+ 中的 BlockingCollection 或 ConcurrentBag 数据类型 - 它们应该适合您的任务。 - Ivan Yuriev
3个回答

9
所有方法都会返回一个值,而不会返回引用。
如果它是按值返回的,那么它将是它自己的列表;如果它是一个引用,我仍然有可能使列表被修改。
这是错误的。被返回的值不是列表,而是对列表对象的引用,因为“List”是一个引用类型,所以使用从此方法返回的值的任何代码和直接访问该字段的任何代码都使用对同一列表的引用的不同副本。

5

C#总是按值返回*。然而,在C#中,大多数类型都是引用类型,这意味着该类型的任何变量都是一个引用;而该引用是按值返回的。

(*) 也就是说,直到ref返回使它进入(C# 7?)。


C# 通过引用返回引用类型。 - Bauss
1
@Bauss 不,它不会。它会按值返回所有类型。 - Servy
在他的示例中,函数返回的值将是声明列表的引用。你可以改变引用是完全不同的话题,并与C#缺乏不可变性有关。 - Bauss
1
@Bauss 是的,返回的是,而不是返回的引用,因为该方法(就像C#中的每个单独方法一样)返回一个 - Servy
类的值始终是引用。 - Bauss
1
@Bauss 是的,当从方法返回时,这些引用是按值传递的。 - Servy

4
Pool是一个类型为List<Item>的变量。因此,它保存了对类型为List<Item>的对象的引用,或者它是null。也就是说,当你读取这个值(实际上是GetPool)时,你会得到对这个对象的引用(或null)。
让我们更清楚地说明值类型和引用类型之间的主要区别。int是一个值类型。让我们考虑下面的代码片段。
int a = 4;
int b = a;
a = 5;

上述声明和赋值完成后,a的值为5,b的值为4。为什么?第一条语句将字面值4复制到a中。第二条语句将a的值复制到b中。因此,b的值为4。请注意,这里的a的四与b的四不同(就像您有两本相同的书,一本属于a,另一本属于b)。在第三条语句之后,a的值将为5。
另一方面,类是引用类型。让我们声明以下类:
public Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

现在让我们考虑以下这段代码。

var personA = new Person { FirstName = "Bob", LastName = "Barney" };
var personB = personA;
personA.FirstName = "Jack";

personB = personA;

the value of personA.FirstName is assigned to personB.FirstName. Therefore, both variables hold the same value.

var personB = personA;

我们有一个“按引用复制”(因为类是引用类型)。从上面提到的书籍范例来看,这意味着什么?现在就像我们扔掉了一本实体书并分享了一个URL,在其中我们可以阅读这本书。由于我们拥有相同的引用,当页面30中的内容发生变化时,这将对我们双方都可见。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接