所以我有一个简单的字符串数组。将它传递给一个反转其输入的函数,然后显示数组的内容。我期待数组的内容反转,因为数组是通过引用传递的,但是字符串数组没有改变。
string[] words = { "Metal", "Gear", "is", "Awesome!" };
mutateArray(ref words);
foreach (string word in words)
Console.Write(word + " ");
这是我的mutateArray
功能:
public static void mutateArray(ref string[] arr)
{
arr = arr.Reverse().ToArray();
}
我知道,一旦我声明必须使用关键字mutateArray
传递参数,数组的ref
方法更改将会保留。
classes
,interfaces
,array
,delegates
)之间的区别是什么(使用关键字ref
)?答案 0 :(得分:2)
这并不是你所期望的原因是Reverse()实际上并没有反转数组的内容,而是创建了一个带有反向内容的 new 列表。原版的。这就是为什么一旦你通过引用传递数组它就可以工作的原因:然后,你实际上用在mutateArray中创建的新数组替换调用方法中的整个原始数组。
如果你有一个在原地进行反转的方法,你可以传入原始数组(不使用ref
),在方法调用之后,数组的顺序会相反。
答案 1 :(得分:1)
您将参考类型与参考传递混淆。 ref
关键字可以应用于值和引用类型。默认情况下,即使引用类型也没有通过引用传递。而是通过值将引用传递给方法。
根据MSDN的文档,他们应该这样做。这就是将ref
关键字与参考类型结合使用的全部目的。
不同之处在于,当您通过引用传递引用类型时,您可以更改原始变量的引用,而不仅仅是方法中的实例。查看以前链接的文档以获取更多详细信息。
答案 2 :(得分:1)
默认情况下,所有参数都按值传递给C#。对于像array这样的引用类型,这意味着引用按值传递。
ref
使变量通过引用传递给函数。这实际上意味着arr
中的mutateArray
参数是调用方中words
的别名。这就是arr
的分配导致words
退出后mutateArray
的变化的原因。
按值将引用类型传递给函数意味着引用的副本。如果没有ref
修饰符,arr
中的mutateArray
是一个不同的变量,其中包含对调用者中words
的同一对象的引用。在这种情况下,分配给arr
对调用者中的words
没有影响。请注意,您可以通过共享引用变更数组,但arr
和words
是单独的存储位置。
答案 3 :(得分:0)
words是对数组的引用。只要考虑它包含该数组的内存地址。
当您将MutateArray作为参数(不包含ref关键字)提供给它时,其VALUE将被复制到arr中。所以arr是一个不同的变量作为单词,但它们包含相同的值(=内存地址)。这意味着它们引用相同的对象(字符串数组)。
你可以改变对象的内容,但是单词(和arr)仍然会引用它。
如果将arr指定给其他对象,则其值会更改,因此它将引用与单词不同的对象。
但是,如果使用ref关键字,则arr和words是SAME变量。这意味着如果您更改了arr的值(=将其指定给新对象),您也会更改单词的值,因此单词将引用相同的新对象。
也许所有这些在技术上都不是100%正确,但我想用它来思考它是如何工作的。
ref关键字是以下Swap方法在C#中工作的原因;没有它,它只会改变Swap方法的内部变量(并且根本没有做任何事情)
public void Swap<T>(ref T a, ref T b) {
T temp = a;
a = b;
b = temp;
}
答案 4 :(得分:0)
你的问题完全可以理解,有一会儿我也很困惑 所以这是解释。
假设您有一个引用类型实例,您可以从中获取数据库中的值。
using (var context = new MyAdventureWorksEntities2())
{
Product p = context.Products.Where(item => item.ProductID == 1000).First();
Console.WriteLine(p.Name); // p.Name = "INITIAL NAME"
UpdateName(p);
Console.WriteLine(p.Name);
}
这是您的UpdateName
方法:
public static void UpdateName(Product p)
{
p.Name = "UPDATED NAME";
}
此代码会发出以下结果:
INITIAL NAME
UPDATED NAME
但是,如果您将方法更改为以下内容:
public static void UpdateName(Product p)
{
using (var context = new MyAdventureWorksEntities2())
{
p = context.Products.Where(item => item.ProductID == 1003).First();
// p.Name = "ANOTHER PRODUCT NAME"
}
}
你的结果将是:
INITIAL NAME
INITIAL NAME
请注意,我根本没有触及ref
关键字
也许在这些例子之后,简短描述将更容易理解。