C# foreach 中未使用变量的警告
我有以下代码(简化):
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# 不太有经验。
I've got the following code (simplified) :
IEnumerable MyFunc(...){
IAsyncResult res = mSocket.BeginReceive(mReceptionArray, 0, pNbBytes, SocketFlags.None, null, null);
while (!res.IsCompleted){
yield return new WaitForFixedUpdate();
}
}
Which can be used like this :
foreach(object o in MyFunc());
Of course, the compiler complains because o
is never used. Is there any way around that ?
EDIT
The foreach is executed in a coroutine. I need to block the execution of the coroutine until I receive data from a server. I could use a regular Receive(), but this would block all other coroutines, and I can't do that : there are lots of other coroutines running, and blocking this one with Receive or EndReceive would block them.
Anyway, this is not a busy-wait.
Any suggestion to refactor the code is more than welcome, I'm not very experienced with C#.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我会编写一个新的扩展方法来使用序列并忽略结果。例如:
然后在调用代码中就可以清楚地看出您正在做什么,并且您故意只是使用序列并忽略结果。
就像 Sixlettervariables 一样,并不清楚您的序列是否合适,但如果您只是想使用一个序列,那就是我会做的。
I would write a new extension method to consume the sequence and ignore the results. For example:
It's then clear in the calling code what you're doing, and that you're deliberately just consuming the sequence and ignoring the results.
Like sixlettervariables, it's not really clear that your sequence is an appropriate one, but if you did just want to consume a sequence, that's what I'd do.
看到你所做的事情后,我真的认为这不是你想要的。您已经使用
foreach
语句实现了忙等待。您已经说过这样做是为了不阻塞其他协程,但我不明白繁忙等待循环如何不会阻塞其他协程。每个
.Begin*
有一个对应的.End*
它将优雅地挂起线程的执行,直到异步操作完成。After seeing what you're doing, I really don't think this is what you want. You've implemented a busy-wait using a
foreach
statement. You've stated that this is done so as to not block other coroutines, but I cannot see how a busy-wait loop won't block other coroutines as well.Every
.Begin*
has a corresponding.End*
which will gracefully suspend execution of the thread until the asynchronous operation completes.并创建一个空白方法:
And create a blank method:
这是 Javad_Amiry 的答案的一个变体(顺便说一下,我+1):
因为它是一个扩展方法,所以您可以使用以下语法从任何地方调用它:
现在以防万一有人想知道,我确实尝试添加
[ Conditional("NEVER_COMPILE_ME")]
位于其上方,但遗憾的是这会导致警告再次出现。顺便说一句,根据我使用 Unity 的经验,
yield return null
根本不会杀死协程。但您的代码实际上是一个忙等待,因为您没有将协程交给 Unity 来运行 - 您自己运行它。在您的代码中,您构造的WaitForFixedUpdate
对象只是以o
(或null
的方式)出现,您可以忽略它并再次循环; Unity从来没有看到过它。如果您希望 UnityWaitForFixedUpdate
或其他任何操作,您必须通过调用StartCoroutine(MyFunc())
来授予它对协程的控制权。它是MonoBehaviour
上的一个实例方法,只要MonoBehaviour
保持启用状态,协程就会运行完成。希望能澄清:)编辑 - 我刚刚注意到你说“foreach”本身是在协程内运行的。在这种情况下,您可以这样做:
或者等效的单行版本:
这将告诉 Unity 等待另一个协程完成,然后再继续执行此协程。
或者,如果您需要稍低的级别,您可以这样做:
Here's a variant on Javad_Amiry's answer (which I +1'd by the way):
Because it's an extension method, you can call it from anywhere using the following syntax:
Now just in case anyone wonders, I did try adding
[Conditional("NEVER_COMPILE_ME")]
above it, but sadly that causes the warning to come back.By the way, in my experience with Unity,
yield return null
doesn't kill the coroutine at all. But your code is effectively a busy-wait because you're not giving the coroutine to Unity to run - you're running it yourself. With your code, theWaitForFixedUpdate
object you constructed just comes through aso
(ornull
does), and you ignore it and go round again; Unity never sees it. If you want Unity toWaitForFixedUpdate
or whatever else, you have to give it control of the coroutine by callingStartCoroutine(MyFunc())
. It's an instance method onMonoBehaviour
, and the coroutine will run to completion as long as theMonoBehaviour
remains enabled. Hope that clarifies :)EDIT - I just noticed you said the 'foreach' itself is run inside a coroutine. In that case, you can do this:
Or the equivalent one-line version:
That'll tell Unity to wait for the other coroutine to finish before continuing with this coroutine.
Or you can do this if you need a slightly lower level:
你的代码看起来很奇怪——当你立即阻塞直到它完成时,为什么你还要费心在套接字上使用异步 I/O 方法?
这会抑制你的警告:
但是在你做类似的事情之前想想是否有更好的方法。请参阅乔恩的回答。
Your code looks odd - why are you bothering to use asychronous I/O methods on the socket when you're immediately blocking until it's finished anyway?
This will suppress your warning:
But think if there's a better way before you do something like that. See Jon's answer.
不是最有效的,但肯定很短:
Not the most efficient, but certainly short: