在C#函数参数中提及ref
我创建了一个函数,并在其中传递字符串数组,如string[]aa=null在C#函数参数中提及ref,c#,c#-4.0,C#,C# 4.0,我创建了一个函数,并在其中传递字符串数组,如string[]aa=null 在函数定义中,我对它进行了一些更新,然后我发现在执行/返回函数时,它的值没有更新。我无法理解C#中哪些内容需要提到ref关键字。它不是总是通过引用传递参数吗?为什么需要提到ref?哪些是需要用ref提及的对象,以便通过引用传递 代码是这样的,只是试图显示我在做什么,我无法在不使用ref的情况下更新值 string[] temp = null foo(ref temp); //function definition v
在函数定义中,我对它进行了一些更新,然后我发现在执行/返回函数时,它的值没有更新。我无法理解C#中哪些内容需要提到ref关键字。它不是总是通过引用传递参数吗?为什么需要提到ref?哪些是需要用ref提及的对象,以便通过引用传递 代码是这样的,只是试图显示我在做什么,我无法在不使用ref的情况下更新值
string[] temp = null
foo(ref temp);
//function definition
void foo (ref string[] temp)
{
temp = {"Hello World ","You must be updated now"}
}
foreach(string s in temp)
System.Console.WriteLine(s)
你在错综复杂的问题上有点弄错了。如果您传递一个引用对象,那么它将按值传递引用(继续阅读,希望它会变得更有意义)。但是,这并不意味着它是按ref传递的。事实上,默认情况下,C#参数是按值传递的 这段代码解释了我所说的按值传递引用的意思 在C#中,参数(默认情况下)通过值传递,这意味着 它们在传递给方法时被隐式复制。对于值类型 参数,这意味着物理复制实例(在相同的 p2的复制方式),而对于引用类型,它意味着复制 参考(以相同的方式复制f2) 。但是,在您的例子中,您正在传入对象,然后在方法中使用新引用创建一个新对象。因此,原始引用保持不变,您可以通过执行更新而不是全新创建来看到这一点。当您显式地说ref时,您现在正在向引用传递一个引用,因此它可以工作,因为您只使用指向该引用的指针,并且当您创建新对象时,它将被放置到该引用位置 正如eouw0o83hf所提到的,如果您正在创建一个全新的对象,那么您应该使用
out
来表示这一点ref
通常更多地用于不通过引用传递的值对象
总结如下:
- 如果它是一种值类型,并且您希望更新该值并使其处处反映,则需要使用
ref
- 如果是引用类型
- 如果您希望更新该值,使其反映在所有地方,则可以正常地传递它(无
或ref
)out
- 如果您希望在方法中创建一个全新的实例并将其反映出来,那么应该使用
out
- 如果您希望更新该值,使其反映在所有地方,则可以正常地传递它(无
你在错综复杂的问题上有点弄错了。如果您传递一个引用对象,那么它将按值传递引用(继续阅读,希望它会变得更有意义)。但是,这并不意味着它是按ref传递的。事实上,默认情况下,C#参数是按值传递的 这段代码解释了我所说的按值传递引用的意思 在C#中,参数(默认情况下)通过值传递,这意味着 它们在传递给方法时被隐式复制。对于值类型 参数,这意味着物理复制实例(在相同的 p2的复制方式),而对于引用类型,它意味着复制 参考(以相同的方式复制f2) 。但是,在您的例子中,您正在传入对象,然后在方法中使用新引用创建一个新对象。因此,原始引用保持不变,您可以通过执行更新而不是全新创建来看到这一点。当您显式地说ref时,您现在正在向引用传递一个引用,因此它可以工作,因为您只使用指向该引用的指针,并且当您创建新对象时,它将被放置到该引用位置 正如eouw0o83hf所提到的,如果您正在创建一个全新的对象,那么您应该使用
out
来表示这一点ref
通常更多地用于不通过引用传递的值对象
总结如下:
- 如果它是一种值类型,并且您希望更新该值并使其处处反映,则需要使用
ref
- 如果是引用类型
- 如果您希望更新该值,使其反映在所有地方,则可以正常地传递它(无
或ref
)out
- 如果您希望在方法中创建一个全新的实例并将其反映出来,那么应该使用
out
- 如果您希望更新该值,使其反映在所有地方,则可以正常地传递它(无
ref
或out
修饰符
string[] temp = { "zero", "one", "two" };
MutateByVal(temp);
MutateByRef(ref temp);
void MutateByVal(string[] arr)
{
// arr and temp are separate references to the same array
// the value of arr (a reference) is a copy of the value of temp
// mutate the array referenced by arr
arr[1] = "mutated!";
// arr and temp still point at the same array
// so both arr and temp now contain { "zero", "mutated!", "two" }
// re-assign arr
arr = new[] { "blah", "blah", "blah" };
// arr and temp now point at different arrays
// arr now contains { "blah", "blah", "blah" }
// temp still contains { "zero", "mutated!", "two" }
}
void MutateByRef(ref string[] arr)
{
// arr is an alias for temp
// that is, they are two different names for the same reference
// mutate the array referenced by arr
arr[1] = "mutated!";
// arr and temp are the same reference
// so both arr and temp now contain { "zero", "mutated!", "two" }
// re-assign arr
arr = new[] { "blah", "blah", "blah" };
// arr and temp are the same reference
// so both arr and temp now contain { "blah", "blah", "blah" }
}
C始终按值传递参数,除非使用ref
或out
修饰符
string[] temp = { "zero", "one", "two" };
MutateByVal(temp);
MutateByRef(ref temp);
void MutateByVal(string[] arr)
{
// arr and temp are separate references to the same array
// the value of arr (a reference) is a copy of the value of temp
// mutate the array referenced by arr
arr[1] = "mutated!";
// arr and temp still point at the same array
// so both arr and temp now contain { "zero", "mutated!", "two" }
// re-assign arr
arr = new[] { "blah", "blah", "blah" };
// arr and temp now point at different arrays
// arr now contains { "blah", "blah", "blah" }
// temp still contains { "zero", "mutated!", "two" }
}
void MutateByRef(ref string[] arr)
{
// arr is an alias for temp
// that is, they are two different names for the same reference
// mutate the array referenced by arr
arr[1] = "mutated!";
// arr and temp are the same reference
// so both arr and temp now contain { "zero", "mutated!", "two" }
// re-assign arr
arr = new[] { "blah", "blah", "blah" };
// arr and temp are the same reference
// so both arr and temp now contain { "blah", "blah", "blah" }
}
这是因为您实际上返回的是一个全新的对象,而不是修改现有对象上的条目。如果要指定新对象,则应使用
out
下面的示例显示了out
、ref
和常规传递如何在数组arg上工作。如您所见,无论是否指定了ref
,数组都是通过引用传递的;但是,如果返回一个全新的对象,则需要指定out
:
class Program
{
static void Main(string[] args)
{
string[] val;
foo(out val);
Console.WriteLine(string.Join(",", val));
// Output: 1, 2
bar(ref val);
Console.WriteLine(string.Join(",", val));
// Output: modified, 2
bar2(val);
Console.WriteLine(string.Join(",", val));
// Output: modified again, 2
Console.Read();
}
static void foo(out string[] temp)
{
temp = new string[]{"1", "2"};
}
static void bar(ref string[] temp)
{
temp[0] = "modified";
}
static void bar2(string[] temp)
{
temp[0] = "modified again";
}
}
这是因为您实际上返回的是一个全新的对象,而不是修改现有对象上的条目。如果要指定新对象,则应使用
out
下面的示例显示了out
、ref
和常规传递如何在数组arg上工作。如您所见,无论是否指定了ref
,数组都是通过引用传递的;但是,如果返回一个全新的对象,则需要指定out
:
class Program
{
static void Main(string[] args)
{
string[] val;
foo(out val);
Console.WriteLine(string.Join(",", val));
// Output: 1, 2
bar(ref val);
Console.WriteLine(string.Join(",", val));
// Output: modified, 2
bar2(val);
Console.WriteLine(string.Join(",", val));
// Output: modified again, 2
Console.Read();
}
static void foo(out string[] temp)
{
temp = new string[]{"1", "2"};
}
static void bar(ref string[] temp)
{
temp[0] = "modified";
}
static void bar2(string[] temp)
{
temp[0] = "modified again";
}
}
如果没有
ref
,对数组的引用只需复制并传递给方法(通过值-因为引用类型的值void foo (string[] temp) // create a copy of a reference to the string array
{
temp[0] = "Boom"; // temp still points to the same object
}
-------------
string[] temp = new [] {"one", "two", "three"}; //outer variable
foo(temp); // behind the scene we have two variables pointing to the same array
foreach (string s in temp)
System.Console.WriteLine(s);
//function definition
void foo (ref string[] temp)
{
if(temp == null)
{
temp = new string[] { "Hello World ", "You must be updated now" };
}
else
{
// do something with the existing temp
}
}
string[] temp = null;
foo(ref temp);
foreach (string s in temp)
System.Console.WriteLine(s);
//function definition
void foo (ref string[] temp)
{
temp = new string[] { "Hello World ", "You must be updated now" };
}