Considere los siguientes métodos ( fiddle ):
void test(Span<int> param) { //Fail, the stackalloc'ed buffer could be exposed. param = stackalloc int[10]; } void test2(Span<int> param) { //OK Span<int> local = stackalloc int[10]; }
No entiendo por qué param = stackalloc int[10];
produce el error:
Un resultado de una expresión
stackalloc
de tipo 'Span' no se puede usar en este contexto porque puede estar expuesto fuera del método que lo contiene.
Span
es una ref struct
pero (a pesar de su nombre) sigue siendo un tipo de valor, por lo que cualquier modificación a param
no se reflejará en el objeto que llama.
Pienso en param
como una variable local con un valor inicial y no veo por qué test2
compila mientras que test
no lo hace.
¿Cómo puede el valor devuelto de stackalloc int[10]
en la test
escapar del alcance del método?
Sinatr publicó un enlace ( aquí la parte relevante ) en los comentarios que me ayudó a poner todo el código en el contexto de la seguridad de Span .
En la test
del método, es seguro devolver el parámetro param
porque podemos pretender que era como una variable local inicializada con un valor dado por la persona que llama (y, por lo tanto, al ser externo al método, es seguro devolverlo).
Cuando un local está marcado como seguro para devolver, el compilador evitará cualquier asignación con valores que no sean seguros para devolver (las expresiones stackalloc
son seguras para escapar al alcance superior del método pero no son seguras para devolver, obviamente).
El hecho de que el método sea nulo no importa (ni para mí como autor de la pregunta, ni para el compilador) ya que esta regla es general (no veo mucho beneficio en el manejo de estos casos de esquina).
Para completar, este código no compila:
void test2(Span<int> param) { //Fail, because local is marked safe to return Span<int> local = param; local = stackalloc int[10]; }
Esta era la pieza que faltaba que estaba buscando.