Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

412
Vistas
En C#, ¿por qué no puedo completar una variable local usando su dirección y luego usar la variable más tarde?

Considere el siguiente código:

 private unsafe void Function() { int length; // This line raises error CS1686, "Local 'length' or its members cannot have their address taken and be used inside an anonymous method or lambda expression". glGetProgramiv(1, GL_PROGRAM_BINARY_LENGTH, &length); FunctionWithLambda(() => Console.WriteLine(length)); } private void FunctionWithLambda(Action callback) { callback(); }

Tenga en cuenta que estoy tomando la dirección de length (una variable local), luego uso la variable en sí ( no su dirección) en una lambda. Entiendo por qué una dirección de variable local no se puede usar en una lambda directamente (consulte ¿Por qué no puedo pasar la dirección de una variable a una función anónima? , entre otros ejemplos), pero ¿por qué no puedo usar el valor de length una vez? asignado (incluso si esa asignación usa el operador & )? La documentación oficial del error CS1686 (https://docs.microsoft.com/bs-latn-ba/dotnet/csharp/misc/cs1686 ) no ha aclarado esta confusión.

Mi suposición es que esto es simplemente una limitación de idioma, pero tengo curiosidad por saber si hay una razón técnica subyacente por la que me estoy perdiendo. También tenga en cuenta que no estoy preguntando cómo solucionar este problema (sé que primero puedo copiar fácilmente la length a otra variable local).

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

La especificación de C# dice lo siguiente (en negrita) :

23.4 Variables fijas y móviles

El operador de dirección (§23.6.5) y la declaración fixed (§23.7) dividen las variables en dos categorías:
Variables fijas y variables móviles .

...recorte...

El operador & (§23.6.5) permite obtener la dirección de una variable fija sin restricciones. Sin embargo, debido a que una variable móvil está sujeta a reubicación o eliminación por parte del recolector de basura, la dirección de una variable móvil solo se puede obtener utilizando una declaración fixed (§23.7), y esa dirección sigue siendo válida solo durante la duración de esa declaración fixed .

En términos precisos, una variable fija es una de las siguientes:

  • Una variable que resulta de un nombre simple (§12.7.3) que hace referencia a una variable local, un parámetro de valor o una matriz de parámetros, a menos que la variable sea capturada por una función anónima (§12.16.6.2).
  • .....

Por lo tanto, está explícitamente prohibido por la especificación. En cuanto a por qué está prohibido, tendrías que preguntarle a los diseñadores del lenguaje, pero teniendo en cuenta la complejidad involucrada en la captura de variables, es algo lógico.

over 4 years ago · Santiago Trujillo Denunciar

0

Supongo que la razón es simple: Demasiado complejo para compilar .

Hay 2 problemas que el compilador tiene que resolver:

  1. Genere un curso para el método anónimo.
  2. Sincroniza el valor de la variable.

Supongamos que los siguientes códigos son válidos.

 unsafe void Function() { int length = 1; void bar() => Console.WriteLine(length); bar(); foo(&length); bar(); } unsafe void foo(int* i) { (*i)++; }

El resultado esperado es:

 1 2

Para resolver el primer problema, C# generará una clase anónima para mantener el valor superior.

Aquí está el pseudocódigo:

 class _Anonymous { public int _length; public void _bar() { Console.WriteLine(_length); } } unsafe void Function() { int length = 1; var a = new _Anonymous { _length = length }; a._bar(); foo(&length); a._bar(); }

Para resolver el segundo problema, C# usa el campo generado en lugar de la variable local original.

 unsafe void Function() { //int length = 1; var a = new _Anonymous { _length = 1 }; a._bar(); foo(&a._length); a._bar(); }

Estos son todos los trabajos que puede hacer un compilador. Pero hasta ahora los códigos siguen sin funcionar, necesitamos un bloque fijo adicional.

 unsafe void Function() { var a = new _Anonymous { _length = 1 }; a._bar(); fixed (int* p = &a._length) foo(p); a._bar(); }

Entonces, la limitación se puede eliminar con un compilador más inteligente, pero las cosas se vuelven más fáciles si prohibimos este tipo de códigos.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda