从C / C ++迈出C#世界的第一步,所以细节有点模糊。据我所知,类默认通过引用传递,但是例如。列表与LT;串GT;喜欢在:
void DoStuff(List<string> strs)
{
//do stuff with the list of strings
}
和其他地方
List<string> sl = new List<string>();
//next fill list in a loop etc. and then do stuff with it:
DoStuff(sl);
sl 在这种情况下是通过引用传递还是复制,以便我需要重新定义工作函数,如
void DoStuff(ref List<string> strs)以实际作用于 sl 本身而非副本?
答案 0 :(得分:13)
它通过引用传递。 List<T>
是一个类,所有类实例都通过引用传递。
答案 1 :(得分:9)
行为始终如一:通过复制传递。如果参数是一个对象,则复制对象的引用,因此实际上您正在处理相同的对象/列表/无论如何。
答案 2 :(得分:4)
基础的东西总是:值类型按值传递,引用类型“通过引用传递”(引用因为引用的值实际上是通过值传递的,但大多数人为了简洁起见忽略了它)
将ref
关键字与引用进行协调的最简单方法是:引用类型的引用按值传递。在标准情况下,这会简单地将引用传递给列表(而不是整个列表)到该方法。
ref
关键字在引用类型上使用时,会在语义上传递对引用的引用(我真的很难不说“指向指针”)。
如果您的方法是将ref
参数重新分配给新对象,则调用者也会看到此新分配。如果没有ref
关键字,该方法只需重新分配自己的参考值本地副本,而调用者仍然可以引用其原始对象。
以上解释是从Jon Skeet's article on the topic:
无耻地进行的这种差异对于理解参数绝对至关重要 传递C#,这就是为什么我认为这样说非常混乱 默认情况下,对象通过引用传递而不是正确的 声明对象引用默认按值传递。
只有在您打算重新分配参数并使其对调用者可见时,才需要ref
关键字。在大多数情况下,您会发现不需要它。您可以重新编写DoStuff
以删除它,并仍然按值成功传递对列表的引用:
void DoSomething(List<string> strs)
{
strs.Add("Hello");
}
答案 3 :(得分:4)
除了其他答案之外,了解ref
的行为非常重要以下是一些用于演示目的的示例代码
static void Main(string[] args)
{
List<string> lstStr = new List<string>();
lstStr.Add("First");
lstStr.Add("Second");
Alter(lstStr);
//Alter(ref lstStr);
Console.WriteLine("---From Main---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Alter2(ref lstStr);
Console.WriteLine("---From Main after passed by ref---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
static void Alter(List<string> lstStr2)
{
lstStr2.Add("Third");
Console.WriteLine("----From Alter----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
lstStr2 = new List<string>();
lstStr2.Add("Something new");
Console.WriteLine("----From Alter - after the local var is assigned somthing else----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
static void Alter2(ref List<string> lstStr2)
{
lstStr2 = new List<string>();
lstStr2.Add("Something new from alter 2");
Console.WriteLine("----From Alter2 - after the local var is assigned new list----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
//----From Alter----
//First
//Second
//Third
//----From Alter - after the local var is assigned somthing else----
// Something new
// ---From Main---
// First
// Second
// Third
// ----From Alter2 - after the local var is assigned new list----
// Something new from alter 2
// ---From Main after passed by ref---
// Something new from alter 2
答案 4 :(得分:2)
如果要修改原始列表,方法中的ref
关键字是多余的:List<T>
是C#中的引用类型(class
),因此将传递给方法引用;因此该方法将操纵原始列表。
传递Value Type
时,它会创建值本身的副本。
传递Reference Type
时,它将创建引用的副本。
详细了解C#中的Value and Reference Types。
答案 5 :(得分:2)
列表以引用方式传递。这意味着实际上方法中的strs变量引用与方法外的sl变量相同的列表。 如果你使用ref,你实际上可以在方法中重新分配sl变量。
strs = new List<string>()
会使sl指向新列表。
由于您来自C / C ++:ref可被视为安全指针&#39;。它类似于使用&amp; strs
答案 6 :(得分:-1)
它的参考。没有必要包括“ref”。
最好的问候。