C# 带有ref的扩展方法不适用于数组

C# 带有ref的扩展方法不适用于数组,c#,generics,extension-methods,C#,Generics,Extension Methods,我写了这段代码: 公共静态T[][]使用where T:struct填充此ref T[][]arg,T { 对于int i=0;i

我写了这段代码:

公共静态T[][]使用where T:struct填充此ref T[][]arg,T { 对于int i=0;i
为什么这样不行?当这个被拿走时,类似的情况也会起作用,不是吗?这些限制似乎得到了满足:我指定T必须是一个struct;我知道arg实际上是一个数组,但这有什么区别呢?数组是否默认通过引用传递,因此无效

我能写一些不会产生错误的等价语句吗


唷,很抱歉问了这么多问题。谢谢。

这是因为数组是引用类型。 因此,您所拥有的是对一个数组的引用,该数组包含对包含结构的数组的其他引用。仅仅因为数组的内容是一个结构,并不意味着数组本身就是一个结构


传递数组时不需要使用ref,只要只更改内容而不更改引用,因为正如前面所述,它们是引用类型。这意味着,如果只删除ref关键字,该函数应该具有您想要的确切行为

现在,我相信这将帮助您解决错误。但是,我没有说明为什么您不能将ref用于扩展方法,同时已经发布了,所以也请查看:

编辑: 我只是想补充一点。您实际上不需要再次返回数组,因为您所做的只是更改数组中的内容,毕竟,它只是一个引用,所以这些更改无需再次返回数组

如果您:

a。更改当前范围中的引用,并且不使用ref关键字
B您希望将调用串在一起,即使您正在使用引用类型创建一点语法糖分语法,如app.UseX.UseY.UseZ

这是因为数组是引用类型。 因此,您所拥有的是对一个数组的引用,该数组包含对包含结构的数组的其他引用。仅仅因为数组的内容是一个结构,并不意味着数组本身就是一个结构


传递数组时不需要使用ref,只要只更改内容而不更改引用,因为正如前面所述,它们是引用类型。这意味着,如果只删除ref关键字,该函数应该具有您想要的确切行为

现在,我相信这将帮助您解决错误。但是,我没有说明为什么您不能将ref用于扩展方法,同时已经发布了,所以也请查看:

编辑: 我只是想补充一点。您实际上不需要再次返回数组,因为您所做的只是更改数组中的内容,毕竟,它只是一个引用,所以这些更改无需再次返回数组

如果您:

a。更改当前范围中的引用,并且不使用ref关键字 B您希望将调用串在一起,即使您正在使用引用类型创建一点语法糖分语法,如app.UseX.UseY.UseZ

ref必须在方法声明中和调用时指定

如果扩展的this参数可以通过引用传递,那么在调用该方法时将无法指定它

someObject.CallSomeExtensionMethod();
我们把ref放在哪里?什么地方都没有

如果我们可以通过引用传递一个值,而不知道我们是通过引用传递它,那么奇怪的事情就会发生。调用修改作为第一个参数传递的值的扩展方法是正常的。例如,我们可以编写一个扩展方法来洗牌列表:

list.Shuffle();
我们希望名单会被修改。但是想象一下,如果扩展方法实际上导致list指向一个完全不同的list实例,我们会感到惊讶。即使我们知道它正在发生,那也会很奇怪,但如果这种行为不明确,那将是混乱的。我们可以调用一个不是ref的扩展,有人可以在不破坏任何东西的情况下将其更改为ref,从而引入各种疯狂的、不可预测的效果

在方法和使用位置中都有ref就像一个契约——该方法告诉我们它可能会取代我们的引用,并且我们给予它明确的许可

ref必须在方法声明中和调用时指定

如果扩展的this参数可以通过引用传递,那么在调用该方法时将无法指定它

someObject.CallSomeExtensionMethod();
我们把ref放在哪里?什么地方都没有

如果我们可以通过引用传递一个值,而不知道我们是通过引用传递它,那么奇怪的事情就会发生。调用修改作为第一个参数传递的值的扩展方法是正常的。例如,我们可以 使用扩展方法洗牌列表:

list.Shuffle();
我们希望名单会被修改。但是想象一下,如果扩展方法实际上导致list指向一个完全不同的list实例,我们会感到惊讶。即使我们知道它正在发生,那也会很奇怪,但如果这种行为不明确,那将是混乱的。我们可以调用一个不是ref的扩展,有人可以在不破坏任何东西的情况下将其更改为ref,从而引入各种疯狂的、不可预测的效果


在方法和使用位置中都有ref就像一个契约——该方法告诉我们它可能会取代我们的引用,并且我们给予它明确的许可

数组不是结构,即使它的成员是。是不是数组默认按引用传递数组,就像所有类型一样,默认按值传递。仅当显式使用ref、in或out时,才通过引用传递类型。传递的值本身只是引用类型(如数组)的引用。但是它是按值传递还是按引用传递与您无关,因为您没有更改变量,您只是在使用它的值。数组不是结构,即使它的成员是。数组是按引用默认传递的吗?与所有类型一样,数组也是按值默认传递的。仅当显式使用ref、in或out时,才通过引用传递类型。传递的值本身只是引用类型(如数组)的引用。但是它是按值传递还是按引用传递与您无关,因为您没有更改变量,您只是在使用它的值。在传递不在所示代码中的数组时,您不需要使用ref。如果您希望能够实际更改变量,或者如果在调用方法后观察变量的更改非常重要,并且不只是访问提供的数组而不希望它在调用过程中更改,那么,那么您需要使用一个引用参数。这实际上也不能回答为什么扩展方法不能为第一个参数使用ref参数的问题。那么您将如何在这里使用ref关键字?此外,OP创建的方法非常基本,不需要ref关键字,因为它们使用的是数组。谢谢。这是否意味着在另一个扩展方法中初始化arg数组是不可能的?我想我不完全理解你的意思,对不起。正如代码所示,如果不使用ref关键字,则填充数组没有问题。唯一不能做的事情是为arg分配一个新数组。当然可以,但它只会更改当前方法中的引用,而不会更改最初传入的引用。在传递不在所示代码中的数组时,不需要使用ref。如果您希望能够实际更改变量,或者如果在调用方法后观察变量的更改非常重要,并且不只是访问提供的数组而不希望它在调用过程中更改,那么,那么您需要使用一个引用参数。这实际上也不能回答为什么扩展方法不能为第一个参数使用ref参数的问题。那么您将如何在这里使用ref关键字?此外,OP创建的方法非常基本,不需要ref关键字,因为它们使用的是数组。谢谢。这是否意味着在另一个扩展方法中初始化arg数组是不可能的?我想我不完全理解你的意思,对不起。正如代码所示,如果不使用ref关键字,则填充数组没有问题。唯一不能做的事情是为arg分配一个新数组。可以,但它只会更改当前方法中的引用,而不会更改最初传入的引用。