C
Join ServerC#
help
❔ Return IEnumerable backwards
IIce_trooper1/24/2023
Hey! I got a method which returns a specific collection depending of the parameter. Right now, I needed to add a method to return similar result, but
How can I do it in the more compact way (and without errors)?
Left.Lane
collection should be returned in backward order.How can I do it in the more compact way (and without errors)?

IIce_trooper1/24/2023
Old, working method:
public IEnumerable<T_Road_Lanes_LaneSection_Lr_Lane> GetLanes (LaneSide side)
{
return side switch
{
LaneSide.Left => Left != null ? Left.Lane : Enumerable.Empty<T_Road_Lanes_LaneSection_Lr_Lane>(),
LaneSide.Right => Right != null ? Right.Lane : Enumerable.Empty<T_Road_Lanes_LaneSection_Lr_Lane>(),
LaneSide.Center => Center.Lane,
_ => throw new ArgumentOutOfRangeException(nameof(side), side, "This lane side is not a valid value.")
};
}
IIce_trooper1/24/2023
New, not working method (that method should return Left colleciton in reversed order:

Ddont1/24/2023
you could use .Reverse() on the collection i suppose?
IIce_trooper1/24/2023
Reverse will call another IEnumerable, it wouldn't be performent 😅
Tthinker2271/24/2023
unrelated but wtf is that type name
T_Road_Lanes_LaneSection_Lr_Lane
AAntonC1/24/2023
it being an IEnumerable is already bad for perf
AAntonC1/24/2023
make a custom iterator if you care about that
IIce_trooper1/24/2023
External library type
IIce_trooper1/24/2023
I ended with something like this. I don't know how I can simplify this

IIce_trooper1/24/2023
but Reverse built-in method would call another unnecessary IEnumerable 😅
AAntonC1/24/2023
if you make a custom iterator type it won't have to
AAntonC1/24/2023
you can make the iterator reversed and also be a value type
AAntonC1/24/2023
to avoid allocations
AAntonC1/24/2023
if you're just going to foreach over it, it will be better
EEro1/24/2023
You're using enumerables in the first place. You can't possibly be concerned about perf
AAntonC1/24/2023
yeah the functional features in c# are implemented in a way that's quite bad for both perf and memory
AAntonC1/24/2023
it's intentionally made more dynamic
EEro1/24/2023
And what you have there sure can be simplified a good bit
Ddont1/25/2023
dude, com on...
IIce_trooper1/25/2023
I'm working in game dev, so yeah I'm not joking about performance ;p
If I have a list, that is, an indexed collection then I don't want to unnecessarily call an additional IEnumerable to Reverse if I can do it in a more efficient way. I just want to write this in the more compact way.
BTW I changed the above code to
If I have a list, that is, an indexed collection then I don't want to unnecessarily call an additional IEnumerable to Reverse if I can do it in a more efficient way. I just want to write this in the more compact way.
BTW I changed the above code to
yield break
instead of yield return null
because of the error.EEro1/25/2023
yeah again, if you actually did care about perf, you wouldn't use enumerables at all
EEro1/25/2023
foreaching over an enumerable is incredibly costly
EEro1/25/2023
something as simple as
becomes
IEnumerable<int> ints = new int[1];
foreach (int i in ints)
{
Console.WriteLine(i);
}
becomes
IEnumerator<int> enumerator = ((IEnumerable<int>)new int[1]).GetEnumerator();
try
{
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
}
finally
{
if (enumerator != null)
{
enumerator.Dispose();
}
}
Ddont1/25/2023
you're even throwing exceptions...
how many times would this code be called per second?
also, have you tested performance at least?
how many times would this code be called per second?
also, have you tested performance at least?
IIce_trooper1/25/2023
You're right that foreach is more costly than for, but I wouldn't say that so much. Anyway, I've used them here to use the deferred execution functionality 😅
IIce_trooper1/25/2023
This exeception... should be exception. I've made it there only to throw something if someone would add new LaneSide (which should not happen) and it wouldn't be supported here.
This method could be called at least once per frame
This method could be called at least once per frame
Ddont1/25/2023
seems reasonable
and collection size?
and collection size?
IIce_trooper1/25/2023
Reverse would make new allocation for a stack, then loop once over collection, and then again to use it. That's why I'm so reluctant to use the Reverse method
When I code it myself it loops over collection only once and without any allocations. In that case the code is just quite long which I prefer to simplify :f
When I code it myself it loops over collection only once and without any allocations. In that case the code is just quite long which I prefer to simplify :f
IIce_trooper1/25/2023
Quite small (in the worst case max 16)
IIce_trooper1/25/2023
So yeah, IEnumerable for small collection is not great. Still want to use deferred execution.
Ddont1/25/2023
to me spending time optimizing this seems overkill
as of now the only way i personally could think of simplifying it would be going unsafe
as of now the only way i personally could think of simplifying it would be going unsafe
EEro1/25/2023
it's hard to make any suggestions without more context
IIce_trooper1/25/2023
You're probably right. And I don't want to use unsafe hah.
Last question, could this code above be more readable for other programmers?
Last question, could this code above be more readable for other programmers?
IIce_trooper1/25/2023
Should I rewrite something?
EEro1/25/2023
public IEnumerable<T_Road_Lanes_LaneSection_Lr_Lane> GetLanesAwayFromCenterOrder(LaneSide side)
{
return side switch
{
LaneSide.Left => Left?.Lane.Reverse<T_Road_Lanes_LaneSection_Lr_Lane>() ?? Enumerable.Empty<T_Road_Lanes_LaneSection_Lr_Lane>(),
LaneSide.Right => Right?.Lane.Reverse<T_Road_Lanes_LaneSection_Lr_Lane>() ?? Enumerable.Empty<T_Road_Lanes_LaneSection_Lr_Lane>(),
LineSide.Center => Enumerable.Repeat(Center.Lane[0], 1),
_ => // ...
};
}
EEro1/25/2023
what was the issue with this?
Ddont1/25/2023
too slow
EEro1/25/2023
but i don't see how
EEro1/25/2023
i don't understand
EEro1/25/2023
i mean either way, you could
private IEnumerable<T...> LeftReverse
{
get
{
if (Left is null)
yield break;
// forr
}
}
AAkseli1/25/2023
yield return forces an allocation anyways
AAccord1/26/2023
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.