“Не может использовать зафиксированное локальное внутреннее лямбда-выражение”

У меня есть проект XNA 3.0, который скомпилировал очень хорошо в VS2008, но это дает ошибки компиляции в VS2010 (с XNA 4.0 CTP). Ошибка:

Не может использовать зафиксированный локальный 'depthPtr' в анонимном методе, лямбда-выражении, или запросить выражение

depthPtr a fixed float* в массив, который используется внутри a Parallel.For лямбда-выражение от System.Threading. Как я сказал, это скомпилировало и работало очень хорошо на VS2008, но он не делает на VS2010, предназначаясь для.NET 3.5.

Это изменилось в.NET 4.0, и несмотря на это, она не должна все еще компилировать, когда я выбираю.NET 3.5 в качестве целевой платформы? Поиск термина "Не может использовать установленные локальные" урожаи точно один (бесполезный) результат, и в Google и в Bing.

Если это изменилось, какова причина этого? Я могу предположить получать a fixed тип указателя в закрытии мог стать немного странным, это почему? Таким образом, я предполагаю, что это - плохая практика? И прежде чем любой спрашивает: нет, использование указателей не абсолютно очень важно здесь. Я все еще хотел бы знать хотя :)

Править: Согласно просьбе, пример кода (не из моей программы, очевидно), который воспроизводит ошибку:

static unsafe void Main(string[] args)
{
  float[] array = new float[10];

  fixed (float* ptr = array)
  {
    Parallel.For(0, 10, i =>
    {
      ptr[i] = i;
    });
  }
}

Вышеупомянутые компиляции в VS2008 (хорошо, кроме ссылки на Parallel, но любое другое лямбда-выражение сделает), но не делает в VS2010.

6
задан pinckerman 26 November 2013 в 02:15
поделиться

5 ответов

фиксирует указатель на время выполнения блока. Если бы вы хранили делегат для последующего вызова после выхода из блока, сборщик мусора мог бы переместить объект между моментом создания лямбды и моментом ее вызова. Что касается того, почему использование другого фреймворка не помогает, то это потому, что это навязывается языком/компилятором, а не временем выполнения (если бы это было время выполнения, то об этом сообщалось бы через исключение или что-то подобное во время выполнения, а не компилятором во время компиляции).

3
ответ дан 17 December 2019 в 02:25
поделиться

Компилятор правильно отклоняет этот код. Fixed может использоваться только для локальных переменных, а переменные, захваченные замыканием, не являются локальными переменными, они поднимаются в класс, используемый для поддержания состояния для закрытия.

1
ответ дан 17 December 2019 в 02:25
поделиться

Это работает. По сути, мы удалили лямбду, содержащую небезопасный указатель, и заменили ее делегатом экземпляра класса, объявленного внутри блока fixed .

    static unsafe void UnsafeTest(string[] args) {
        float[] array = new float[10];

        fixed(float* ptr = array) {
            UnsafeOps ops = new UnsafeOps();
            ops.p = ptr;

            Parallel.For(0, 10, ops.Lambda);
        }
    }

    unsafe class UnsafeOps {
        public float* p;
        public unsafe void Lambda(int value) {
            p[value] = value;
        }
    }

Мне кажется, что в .NET 4 была добавлена ​​наполовину необдуманная попытка запретить фиксированный доступ к памяти в компиляторе. В приведенном выше блоке кода вы можете определить UnsafeOps вне блока fixed и получить доступ к массиву после блока fixed . Так что это не идеально ...

1
ответ дан 17 December 2019 в 02:25
поделиться

Одно из объяснений может заключаться в том, что значение переменной берется при выполнении закрытия, а не при определении. В вашем примере это, вероятно, не повредит, но в других случаях может. Итак, чтобы научить хорошей практике, вообще запрещено предотвращать всевозможные интересные ошибки.

0
ответ дан 17 December 2019 в 02:25
поделиться

В doco говорится, что вам не разрешается обращаться к опасному коду в анонимных методах, и те же ограничения применяются к лямбдам, так что я думаю, что это может быть вашей проблемой. Нет ли у вас фактической ошибки компилятора?

1
ответ дан 17 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: