IList 是按值传递的吗?

发布于 08-22 22:47 字数 638 浏览 8 评论 0原文

值类型 参数传递给 C# 中的函数是按值传递,除非您使用参数上的 ref 或 out 关键字。但这是否也适用于引用类型

具体来说,我有一个接受 IList 的函数。传递给我的函数的列表是否是列表的副本及其所包含对象的副本?或者对列表的修改也适用于调用者吗?如果是这样 - 有什么聪明的方法可以让我传递一份副本吗?

public void SomeFunction()
{
    IList<Foo> list = new List<Foo>();
    list.Add(new Foo()); 
    DoSomethingWithCopyOfTheList(list);
    ..
}

public void DoSomethingWithCopyOfTheList(IList<Foo> list)
{
    // Do something
}

Passing Value Type parameters to functions in c# is by value unless you use the ref or out keyword on the parameter. But does this also apply to Reference Types?

Specifically I have a function that takes an IList<Foo>. Will the list passed to my function be a copy of the list with copy of its contained objects? Or will modifications to the list also apply for the caller? If so - Is there a clever way I can go about passing a copy?

public void SomeFunction()
{
    IList<Foo> list = new List<Foo>();
    list.Add(new Foo()); 
    DoSomethingWithCopyOfTheList(list);
    ..
}

public void DoSomethingWithCopyOfTheList(IList<Foo> list)
{
    // Do something
}

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

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

发布评论

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

评论(6

千里故人稀2024-08-29 22:47:25

所有参数均按值传递,除非您显式使用 refout。但是,当您传递引用类型的实例时,您是按值传递引用。即引用本身被复制,但由于它仍然指向同一个实例,因此您仍然可以通过此引用修改实例。即实例未被复制。参考是。

如果您想复制列表本身,List 有一个 方便的构造函数,它采用 IEnumerable

All parameters are passed by value unless you explicitly use ref or out. However, when you pass an instance of a reference type, you pass the reference by value. I.e. the reference itself is copied, but since it is still pointing to the same instance, you can still modify the instance through this reference. I.e. the instance is not copied. The reference is.

If you want to make a copy of the list itself, List<T> has a handy constructor, that takes an IEnumerable<T>.

孤千羽2024-08-29 22:47:25

你并不孤单;这让很多人感到困惑。

我喜欢这样想。

变量是一个存储位置。

变量可以存储特定类型的内容。

有两种类型:值类型和引用类型。

引用类型变量的值是对该类型对象的引用。

值类型变量的值是该类型的对象。

形式参数是一种变量。

形式参数分为三种:值参数、引用参数和输出参数。

当您使用变量作为与值形参相对应的实参时,变量的值将被复制到与形参关联的存储中。如果变量是值类型,则创建该值的副本。如果变量是引用类型,则创建引用的副本,并且两个变量现在引用同一个对象。无论哪种方式,都会生成变量值的副本。

当您使用变量作为对应于 out 或 ref 参数的实参时,该参数将成为该变量的别名。当您说:

void M(ref int x) { ...}
...
int y = 123;
M(ref y);

您所说的是“x 和 y 现在是同一个变量”。它们都指相同的存储位置

我发现这比思考别名是如何实际实现的——通过将变量的托管地址传递给形式参数——更容易理解。

清楚了吗?

You're not alone; this confuses a lot of people.

Here's how I like to think of it.

A variable is a storage location.

A variable can store something of a particular type.

There are two kinds of types: value types and reference types.

The value of a variable of reference type is a reference to an object of that type.

The value of a variable of value type is an object of that type.

A formal parameter is a kind of variable.

There are three kinds of formal parameters: value parameters, ref parameters, and out parameters.

When you use a variable as an argument corresponding to a value parameter, the value of the variable is copied into the storage associated with the formal parameter. If the variable is of value type, then a copy of the value is made. If the variable is of reference type, then a copy of the reference is made, and the two variables now refer to the same object. Either way, a copy of the value of the variable is made.

When you use a variable as an argument corresponding to an out or ref parameter the parameter becomes an alias for the variable. When you say:

void M(ref int x) { ...}
...
int y = 123;
M(ref y);

what you are saying is "x and y now are the same variable". They both refer to the same storage location.

I find that much easier to comprehend than thinking about how the alias is actually implemented -- by passing the managed address of the variable to the formal parameter.

Is that clear?

冷情2024-08-29 22:47:25

该列表是通过引用传递的,因此如果您修改 SomeFunction 中的列表,您也会修改调用者的列表。

您可以通过创建新列表来创建列表的副本:

var newList = new List<Foo>(oldList);

The list is passed by reference, so if you modify the list in SomeFunction, you modify the list for the caller as well.

You can create a copy of a list by creating a new one:

var newList = new List<Foo>(oldList);
葬心2024-08-29 22:47:25

您的列表是通过引用传递的。如果你想传递列表的副本,你可以这样做:

IList<Foo> clone = new List<Foo>(list);

如果你在克隆中添加/删除元素,它不会修改列表
但元素本身的修改将在两个列表中考虑在内。

your list is passed by reference. If you want to pass a copy of the list you can do:

IList<Foo> clone = new List<Foo>(list);

if you add/remove elements in clone it won't modify list
but the modifications of the elements themselves will be taken into account in both lists.

总以为2024-08-29 22:47:25

当您按值传递引用类型(没有 ref 或 out 关键字)时,您可以在此方法内修改此引用类型,并且所有更改都将反映到调用者代码。

为了解决您的问题,您可以显式创建一个副本并将该副本传递给您的函数,或者您可以使用:

list.AsReadOnly();

When you pass reference type by value (without ref or out keywords) you may modify this reference type inside this method and all changes will reflect to callers code.

To solve your problem you may explicitly create a copy and pass this copy to your function, or you may use:

list.AsReadOnly();
够钟2024-08-29 22:47:25

传递引用类型时,您传递的是引用。这是一个重要的概念。

如果通过 byref 传递引用

,则直接传递引用(指针)。

byval,您传递引用(指针)的副本。

引用不是引用的实例。引用类似于指针。

要传递引用类型实例的副本,您首先必须自己创建一个副本并传递对该副本的引用。因此,您将不会修改原始实例。

When passing reference types, you pass the reference. This is an important concept.

If you pass a reference

byref, you pass the reference (pointer) directly.

byval, you pass a copy of the reference (pointer).

A reference is not the instance referenced. A reference is analagous to a pointer.

To pass a copy of the instance of a referencetype, you first must make a copy yourself and pass a reference to the copy. As such then you will not be modifying the original instance.

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