所以我遇到了这个错误,其中C#表现得像我通过引用而不是通过值传递列表,就像通常那样。让我举个例子:
using System;
using System.Collections.Generic;
namespace testprogram
{
class Program
{
static int x;
static List<Coordinate> coordinates;
static void Main(string[] args)
{
x = 10;
coordinates = new List<Coordinate>();
coordinates.Add(new Coordinate(0, 0));
coordinates.Add(new Coordinate(1, 1));
testfunction(x, coordinates);
Console.WriteLine(x);
foreach (var objekt in coordinates)
{
Console.WriteLine(objekt.xpos);
Console.WriteLine(objekt.ypos);
}
Console.Read();
}
static void testfunction(int test, List<Coordinate> objects)
{
test = 4;
foreach (Coordinate obj in objects)
{
obj.xpos = 4;
obj.ypos = 4;
}
}
}
class Coordinate
{
public int xpos;
public int ypos;
public Coordinate(int new_x, int new_y)
{
xpos = new_x;
ypos = new_y;
}
}
}
此代码输出:
10
4
4
4
4
但为什么呢?我原以为:
10
0
0
1
1
我试图在Funktion中添加一个额外的List并为其分配参数的值,但即使这样也行不通。有没有解决方法呢?
答案 0 :(得分:1)
List<T>
参数是一个通过值传递的引用类型。
如果修改方法中列表中的任何项目,则在离开方法时这些项目将保持更改。
但是,如果重新分配方法内的引用,则这些更改将在方法外部丢失。如果您想通过引用传递参数,请使用ref
关键字:
static void testfunction(int test, ref List<Coordinate> objects)
{
// This will update objects outside the testfunction method
objects = new List<Coordinate>();
}
您还可以使用out
关键字,该关键字与ref
关键字类似。唯一的区别是,在调用方法之前,您不必初始化作为out
参数传递的值,并且在离开方法之前必须初始化它们。< / p>
static void Main(string[] args)
{
// No need to initialise variable passed as "out" parameter
List<Coordinate> objects;
testfunction(test, out objects);
}
static void testfunction(int test, out List<Coordinate> objects)
{
// Removing this line would result in a compilation error
objects = new List<Coordinate>();
}
答案 1 :(得分:0)
您通过值&#34;传递了对列表&#34;的引用。所以,如果你改变参考&#34;对象&#34;在&#34; testfunction&#34;,然后&#34;坐标&#34;不会改变(作为指针)。但改变&#34;对象&#34;的元素。会影响&#34;坐标&#34;。
的元素答案 2 :(得分:0)
你的期望是错误的。该列表作为值传递。这意味着名为template <class T>
union const_cast_impl {
using CT = const T;
static_assert(std::is_same<CT,const int *>::value, "CT is not const int*");
T data;
CT cdata;
const_cast_impl(CT ptr):cdata(ptr){}
operator T(){
return data;
}
};
int main(){
int a = 2;
const int *ptr = &a;
int *ptr2 = const_cast_impl<int *>(ptr);
}
的变量是原始列表变量的值副本。但是列表包含引用,我的意思是列表的内容是对objects
个对象的引用。因此,如果您尝试更改Coordinate
之类的列表变量,则不会更改原始列表。但是,如果更改列表中的对象,则更改实际应用于原始列表。
objects = new List<>()
这两个示例都会更改原始列表。
如果您希望安全地更改列表中的任何内容,则必须对其进行深层克隆。您可以使用Clone()方法,但这可能很棘手,因为您必须手动克隆列表中的每个对象。这已在这里得到解答: How create a new deep copy (clone) of a List<T>?