- Home /
foreach iteration variable.. null?
i hope i'm not missing something obvious here, but this is the first time i've truly been stumped with unity and actually had to come make my own post
there's nothing that crazy about this loop, but it didn't work as expected, and upon stepping through it, well.. how can h be null?
it also seems to completely step over certain lines within for no reason, i've no clue what's going on here. i've had bugs before with unity where it sort of loses its place among the lines of code, but restarting it/visual studio usually fixes things. this time, no dice
looks weird alright. what I notice is that you try to go without braces. Put em in properly and see if it fixed the issue. my guess is h is null because the first foreach is already done even though the syntax doesn't look like it.
no go, looks like lilius is right, very strange
Just tested foreach, and it seems to do that and still works fine. It just kind of has a "warm up lap" :D . Have no Idea if it is supposed to be like that or what?
yeah that's odd, never seen it in any other applications of c#, i guess i'll just try to roll with it, though the jumping around when i step through the lines is weirding me out a bit too. in the first and all other iterations it just completely skips over some lines when it clearly shouldn't
I've seen this many times before, whenever I debug a foreach statement. When using a foreach, the value during the first "iteration" is always null (I put it between quotations because maybe it is not an actual iteration). Don't know exactly why, it most likely has to do with the inner workings of the statement and how C# handles it. $$anonymous$$y guess is that it first has to prepare the collection in some way to be able to go through it, thus the null value, since it hasn't started iterating at that point.
I always use the standard for
loop. A foreach loop tends to be less efficient (I know, it's a micro-optimization here), and I guess you may not have this problem with the for
loop.
Note: Are you completely mad? You are using a goto
? What's wrong with you? o.O
hah! i see the standard boo-hiss reaction to goto is still going strong. this is one of the few legitimate uses in c# of a goto statement because it does not have a built in way to break out of multiple loops at once like php, for example (i.e. "break 2;")
Answer by Bunny83 · Mar 05, 2018 at 06:33 PM
Well, there could be several reasons why the debugger behaves strange "visually". First of all keep in mind that there is no "for" or "foreach" thing in the common intermediate language. Therefore what code results from a given for / foreach loop depends on the used compiler. Unity uses the Mono C# compiler while visual studio works on the basis of the .NET C# compiler. So those slight differences might result in this weird visual behaviour. Keep in mind that one line of highlevel code often belongs to several lines of IL code. So for a debugger to "step" through the highlevel code it has to know what statements / opcodes belong to the actual source code line.
One reason could be your goto statement. It breaks the usual construct of a foreach loop so VS might not even recognise the foreach properly. I suggest you have a look at the IL code that was generated by using ILSpy on your compiled assembly and switch the language to "IL" to see the "actual" code. The decompilation from IL to C# is usually quite good, however as i said a decompiler can only "assume" based on some opcode patterns what high level code has generated the given IL code.
While it's possible to omit the body brackets of loops and if statements if it only contains a single statement i strongly would recommend to only use this when the statement really is just a single line. Such a complex nested loop-->if-->loop is just confusing and it's easy to miss the exact flow. Code is mainly meant to be easy to write, read and understand by humans. Do not use certain techniques because it's shorter or quicker to write but because it actually improves readability.
Aside from the "why does VisualStudio behave weird" the whole piece of code seems really strange. First of all the innermost if statement has the same condition as the if in the first loop, so it's redundant. $$anonymous$$ost likely you wanted to use "h2" ins$$anonymous$$d of "h". If that's the case all your code does is searching for the first two elements in that array / collection / whatever that are disabled. You seem to just pick the first element that is not null and assign "leader" as his leader. Furthermore you pick the second object that is disabled and make it follow the first one. That's all your code does.
Since both loops iterate over the same array obviously "h" (the first object) will be the first not enabled object in that array. Since your inner loop searches for an element with the same precondition but additionally it should be different from the first one, "h2" will be the next not enabled object after "h".
The same can be achieved with something like this:
Character c1 = null;
foreach(Character c in heros) {
if (!c.Get<RoamController>().enabled) {
if (c1 == null)
c1 = c;
else {
c1.GetComponent<RoamFollower>().leader = leader;
c.GetComponent<RoamFollower>().leader = c1;
break;
}
}
}
that sounds likely, i do hope they make an attempt to clean things up a bit, especially now that they're moving so far in the .net direction
while i appreciate the attempt, your example isn't what it's intended to accomplish. this block of code on its own was quite literally the first thing i wrote down, and within the scope of this question, it's not meant to be anything other than my example of this behavior. it's clearly very messy, the 2 h references were indeed a typo, and the whole thing is easily debugged and cleaned up. nothing within should lead to some of the behaviors i was experiencing, even upon drilling deeper into the IL. also, i suggest taking a closer look; it's not a reasonable to suggest the goto would do anything out of the ordinary, given what's written there. it's a very simple break out of the loop once it reaches that line. at the point where we'd have to start questioning simple logic like that, unity would have made a big mistake somewhere in supporting visual studio in the first place
and yes, code is meant to be easy to read, which is why, outside of the confines of my day job where i do have to follow best practices, within my own little game project, i prefer to forego brackets, as i find what's written above less cluttered and easier to read than what you're suggesting :P
Sorry but that doesn't have much to do with Unity. This is a Visual Studio issue. The debugger belongs completely to VS. As i said the problem might be that the VS debugger can't match the (jitted and) executing IL code with the actual C# code since VS would expect that the code was compiled with the .NET compiler which it probably wasn't.
Apart from that I've experienced some issues myself with plain .NET code. Especially generators / iterators (IEnumerator) can look really strange when debugging as the actual method that is executing looks completely different than the source code. You can find several people who noticed strange debugging experiences in plain .NET / VS like this, or this.
You haven't shown much context to your problem. If this code is in a coroutine or inside a NetworkBehaviour it's possible that the resulting IL looks completely different from what the source code shows. The UNetWeaver runs over the compiled assemblies and altering the code (though this only happens in NetworkBehaviours).
In the end just keep in $$anonymous$$d that it's not the highlevel code that is executed. Not even the IL code is executed since it's jit compiled to native code at runtime. If you have the profiler running in Unity there might be additional code injected which could trip up the debugger.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
I dont know why im getting a null reference exception 1 Answer
Executing coroutines consecutively 0 Answers