对foreach中未使用的变量的C#警告

时间:2011-10-17 16:10:31

标签: c# foreach unity3d coroutine

我有以下代码(简化):

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从未使用过。有没有办法解决这个问题?

修改

foreach在协程中执行。我需要阻止协程的执行,直到我从服务器接收数据。我可以使用常规的Receive(),但这会阻止所有其他协同程序,我不能这样做:有很多其他协同程序在运行,用Receive或EndReceive阻止它会阻止它们。

无论如何,这是忙碌等待。

任何重构代码的建议都非常受欢迎,我对C#不是很有经验。

6 个答案:

答案 0 :(得分:3)

我会写一个新的扩展方法来使用序列并忽略结果。例如:

// 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 :(得分:1)

在看到你在做什么之后,我真的不认为这是你想要的。您已使用foreach语句实现了忙等待。你已经声明这样做是为了不阻止其他协同程序,但我看不出忙等待循环也不会阻止其他协同程序。

Every .Begin*有一个corresponding .End*,可以优雅地暂停执行该线程,直到异步操作完成。

// Suspend execution until the receive operation completes
mSocket.EndReceive(res);

答案 2 :(得分:1)

foreach(object o in MyFunc())
    doNothing(o); // avoiding warning

并创建一个空白方法:

void doNothing(object o){ }

答案 3 :(得分:1)

以下是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永远不会看到它。如果你想要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;

答案 4 :(得分:0)

您的代码看起来很奇怪 - 为什么在您立即阻塞时仍然无法在套接字上使用异步I / O方法,直到它完成为止?

这将取消您的警告:

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

但是想想在你做这样的事情之前有更好的方法。见Jon的回答。

答案 5 :(得分:0)

效率最高,但肯定很短:

MyFunc().Any(x => false);