Как смягчить «Доступ к измененному закрытию» в случаях, когда делегат вызывается напрямую - PullRequest
0 голосов
/ 02 января 2019

Насколько я понимаю, предупреждение "Доступ к измененному закрытию" служит предупреждением о доступе к локальным переменным от делегата, когда делегат может быть сохранен и вызван позже или вызван в другом потоке, так что локальная переменная нефактически доступно во время фактического выполнения кода.Это, конечно, разумно.

Но что, если я создаю делегата, который, как я знаю, будет немедленно вызван в том же потоке?Предупреждение тогда не нужно.Например, предупреждение генерируется в коде:

delegate void Consume();

private void ConsumeConsume(Consume c)
{
    c();
}

public int Hello()
{
    int a = 0;

    ConsumeConsume(() => { a += 9; });

    a = 1;

    return a;
}

Здесь не может быть проблем, поскольку ConsumeConsume всегда вызывает функцию немедленно.Есть ли способ обойти это?Есть ли способ аннотировать функцию ConsumeConsume, чтобы указать ReSharper, что делегат будет вызван немедленно?

Интересно, когда я заменяю строку ConsumeConsume(() => { a += 9; }); на:

new List<int>(new[] {1}).ForEach(i => { a += 9; });

который делает то же самое, предупреждение не генерируется.Это встроенное исключение для ReSharper или я могу сделать что-то подобное, чтобы указать, что делегат вызывается немедленно?

Я знаю, что могу отключить эти предупреждения, но это нежелательный результат.

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Установите пакет JetBrains.Annotations с помощью NuGet: https://www.nuget.org/packages/JetBrains.Annotations

Отметьте переданного делегата атрибутом InstantHandle.

private void ConsumeConsume([InstantHandle] Consume c)
{
    c();
}

Из описания InstantHandle:

Сообщает механизму анализа кода, полностью ли обрабатывается параметр, когда вызываемый метод находится в стеке.Если параметр является делегатом, указывает, что делегат выполняется во время выполнения метода.Если параметр является перечислимым, указывает, что он перечисляется во время выполнения метода.

Источник: https://www.jetbrains.com/help/resharper/Reference__Code_Annotation_Attributes.html

Если вы не хотите добавлять весь пакет вваш проект, достаточно просто добавить атрибут самостоятельно, хотя, на мой взгляд, он хакерский.

namespace JetBrains.Annotations
{
    [AttributeUsage(AttributeTargets.Parameter)]
    public class InstantHandleAttribute : Attribute { }
}
0 голосов
/ 02 января 2019

Да, это только предупреждение, вы можете смягчить его следующим

// ReSharper disable once AccessToModifiedClosure
ConsumeConsume(() => { a += 9; });

Или на уровне файла

// ReSharper disable AccessToModifiedClosure
namespace blah 
{

Или вы можете настроить серьезность проверки, однако я бы не стал выключать ее в полном смысле этого слова, так как это может выявить проблемы

Обновление

Извините, мой вопрос не был достаточно ясен, я думаю. Необходимость отключить Предупреждающие команды везде - не приемлемое для меня решение, я предпочел бы, чтобы ReSharper нашел способ выяснить это. Пример ForEach демонстрирует, что есть, по крайней мере, некоторые существующие исключения.

Вы можете отключить его, но, к сожалению, его никак не понять.

...