我写了这段代码:
public static T[][] Populate<T>(this ref T[][] arg, T with) where T : struct
{
for (int i = 0; i < arg.Length; i++)
{
for (int j = 0; j < arg[i].Length; j++)
{
arg[i][j] = with;
}
}
return arg;
}
然后出现以下错误:
为什么不起作用?将this
带走后,类似的情况会起作用,不是吗?而且似乎满足了这些限制:我指定的T
必须是struct
;我知道arg
实际上是一个数组,但这有什么区别?数组是否默认通过引用传递,所以无效?
我是否可以编写不会产生错误的等效语句?
Ph,对于所有问题,我们深表歉意。谢谢。
答案 0 :(得分:4)
ref
必须在方法声明中以及在调用方法时都指定。
如果扩展名的this
参数可以通过引用传递,则在调用该方法时将无法指定它。
someObject.CallSomeExtensionMethod();
我们将ref
放在哪里?无处。
如果我们可以在没有知道的情况下通过引用传递值,那么可能会发生奇怪的事情。调用扩展方法来修改作为第一个参数传递的值是正常的。例如,我们可以编写一个扩展方法来随机播放列表:
list.Shuffle();
我们希望列表会被修改。但是,如果扩展方法实际上导致list
指向List
的完全不同的实例,我们会感到惊讶。即使我们知道发生的事情也很奇怪,但是如果这种行为不明确,那就太混乱了。我们可以称呼不是ref
的扩展名,有人可以将其更改为ref
而不会破坏任何东西,从而引入各种疯狂的,不可预测的效果。
方法和用法中都ref
就像合同一样-该方法告诉我们它可以代替我们的引用,并且我们给予它明确的许可。
答案 1 :(得分:1)
这是因为数组是引用类型。
因此,您所拥有的是对包含其他引用的包含结构的数组的引用。仅仅因为数组的内容是一个结构并不意味着数组本身就是结构。
传递数组时不需要使用ref(,只要您仅更改内容而不是引用即可),因为如上所述,它们是引用类型。这意味着,如果仅删除ref关键字,则此函数应具有所需的确切行为。
现在,我相信这应该可以帮助您解决错误。但是,我没有说明为什么不能将ref用作扩展方法,而与此同时a really good explanation也已经发布,所以也请检查一下:)
修改:
只是我想添加的内容。您实际上并不需要再次返回该数组,因为您所做的只是在其内部 进行了更改(毕竟,这只是一个参考,因此这些更改都可以进行,而无需再次返回该数组)。
如果您愿意,可以退回它:
a。在当前作用域中更改引用,并且不使用ref关键字
b。即使您使用引用类型来创建一些语法糖(如app.UseX().UseY().UseZ()
这样的语法),也希望将调用串在一起。