C # предупреждение о неиспользуемой переменной в foreach - PullRequest
0 голосов
/ 17 октября 2011

У меня есть следующий код (упрощенно):

IEnumerable MyFunc(...){
    IAsyncResult res = mSocket.BeginReceive(mReceptionArray, 0, pNbBytes, SocketFlags.None, null, null);
    while (!res.IsCompleted){
        yield return new WaitForFixedUpdate();
    }
}

Что можно использовать так:

foreach(object o in MyFunc());

Конечно, компилятор жалуется, потому что o никогда не используется. Есть ли способ обойти это?

EDIT

Foreach выполняется в сопрограмме. Мне нужно заблокировать выполнение сопрограммы, пока я не получу данные с сервера. Я мог бы использовать обычный Receive (), но это заблокировало бы все другие сопрограммы, и я не могу этого сделать: запущено много других сопрограмм, и блокировка этой с помощью Receive или EndReceive заблокирует их.

В любом случае, это , а не занятое ожидание.

Любые предложения по рефакторингу кода приветствуются, я не очень разбираюсь в C #.

Ответы [ 6 ]

3 голосов
/ 17 октября 2011

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

// TODO: Documentation
public static void ConsumeSequence<T>(this IEnumerable<T> source)
{
    // TODO: Argument validation
    using (var iterator = source.GetEnumerator())
    {
        while (iterator.MoveNext())
        {
            // Deliberate no-op
        }
    }
}

Тогда в коде вызова ясно, что вы делаете, и что вы сознательно просто используете последовательность и игнорируете результаты.

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

1 голос
/ 22 декабря 2013

Вот вариант ответа Javad_Amiry (кстати, я + 1):

public static void Unused<T>(this T value) { }

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

foreach (object o in MyFunc())
    o.Unused();

Теперь, на всякий случай, если кто-то задается вопросом, я попытался добавить [Conditional("NEVER_COMPILE_ME")] над ним, но, к сожалению, это вызывает предупреждение.


Кстати, по моему опыту сUnity, yield return null совсем не убивает сопрограмму.Но ваш код, по сути, является занятым ожиданием, потому что вы не предоставляете сопрограмму для запуска Unity - вы запускаете ее самостоятельно.С вашим кодом, WaitForFixedUpdate объект, который вы сконструировали, просто проходит как o (или null делает), и вы игнорируете его и снова вращаетесь;Единство никогда этого не видит.Если вы хотите, чтобы Unity WaitForFixedUpdate или что-то еще, вы должны дать ему контроль над сопрограммой, позвонив по номеру StartCoroutine(MyFunc()).Это метод экземпляра в MonoBehaviour, и сопрограмма будет работать до конца, пока MonoBehaviour остается включенным.Надеюсь, это прояснит:)

РЕДАКТИРОВАТЬ - Я только что заметил, что вы сказали, что сам 'foreach' запускается внутри сопрограммы.В этом случае вы можете сделать это:

var subCoroutine = StartCoroutine(MyFunc());
yield return subCoroutine;

или эквивалентную однострочную версию:

yield return StartCoroutine(MyFunc());

Это скажет Unity дождаться завершения другой сопрограммы, прежде чем продолжитьс этой сопрограммой.

Или вы можете сделать это, если вам нужен немного более низкий уровень:

foreach (object o in MyFunc())
    yield return o;
1 голос
/ 17 октября 2011
foreach(object o in MyFunc())
    doNothing(o); // avoiding warning

И создайте пустой метод:

void doNothing(object o){ }
1 голос
/ 17 октября 2011

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

Каждый .Begin* имеет , соответствующий .End*, который изящно приостановит выполнение потока до завершения асинхронной операции.

// Suspend execution until the receive operation completes
mSocket.EndReceive(res);
0 голосов
/ 17 октября 2011

Не самый эффективный, но, безусловно, короткий:

MyFunc().Any(x => false);
0 голосов
/ 17 октября 2011

Ваш код выглядит странно - почему вы пытаетесь использовать асинхронные методы ввода-вывода в сокете, когда вы сразу же блокируете, пока он не закончится?

Это подавит ваше предупреждение:

#pragma warning disable 0168
// code goes here
#pragma warning restore 0168

Но подумайте, есть ли лучший способ, прежде чем делать что-то подобное. Смотри ответ Джона.

...