- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Ahhh. The billion dollar FRIST!
Admin
That line is not a bug, because of what the "as" operator does in C#. s as IList<SomeObjects> can be null even if s is not null.
Admin
How is this a check for s being equal to null? It checks if s is an IList. Else, it tries to make a list of it.
Admin
There's nothing wrong with that line. The s variable will never be null, so
s.ToList()
is fine.s as IList<T>
might be null, but that's why it falls back tos.ToList()
. The 's as IList<T>part is just there as a possible performance optimization, if
sis already an
IList<T>then we'll use that, otherwise we create an
IList<T>with the contents of
s`.Admin
Actually it can be null. The as operator is type checking what it's passed, an IEnumerable doesn't have to be an IList, what this code does is If it's already an IList it returns it, and if not it actualizes the IEnumerable as a list using the ToList() method of IEnumerable. It would depend on the implementation of the group method on whatever the base collection type is. this can vary a lot for example if it's an EF implementation doing database calls in the background.
Admin
You missed the obvious* "Donald Frist" joke here.
*) obvious if you know Donald Knuth and his statement about null.
Admin
s couldn't be null, but
s as IList<T>
could. I think the goal here is to avoid callingToList()
(which causes a full enumeration and copy of the IEnumerable<T>) if s is already anIList<T>
. Which it is (actually an instance ofGrouping<TKey, TElement>
), unless it's empty (in which case it'sEnumerable.Empty<T>
). So, this code might be a little ugly, but it's not a WTF. I wrote similar code myself, but I usually wrap it in an AsList extension method.Admin
Bjørn, dwaz and That nerd guy are all correct here in that the "as" cast can result in null, even though s is not null.
Which ironically means that today's WTF here isn't so much the submitted code, but that Remy doesn't know C# as well as he thought he did.
Admin
That cast check is unnecessary anyway: if s is already a list, then calling ToList() on it is basically a no-op. So there's no need to check for that special case - just call ToList() on it regardless.
Or better yet, don't, and just leave it as an IEnumerable so that you can continue to enjoy the benefits of deferred execution for as long as possible rather than forcing a resolution right there. That's something I have to deal with in my codebase all the time - gratuitous ToList() calls abound, sometimes as often as every layer in a call stack, rather than building up a query and letting the engine optimize it before it's finally executed.
Admin
@Brian no, ToList is not a noop. It will copy the source to a new list (even if the source is already a list)
Admin
Just to add on the make fun of Remy for not understanding c# crowd;
Elements in the group are ordered according to the order they appear in in the source. https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.groupby?redirectedfrom=MSDN&view=net-5.0#System_Linq_Enumerable_GroupBy__3_System_Collections_Generic_IEnumerable___0__System_Func___0___1__System_Func___0___2__
So sorting the source can make sense.
Assuming the s.PrimaryKey is actually a primary key sorting by primary key, then by anything else does not make sense though.
Admin
He wasn't saying that .ToList() is a no-op, he was saying that "s as IList<SomeObjects> ?? s.ToList()" is "basically" a no-op because it seems from the code above that "s" is always an IList.
Admin
The cast is to IList - ie. the interface. ToList returns List - the class. So if the IList is not actually a List I do not see how toList can be a no-op.
Admin
Less obvious WTF: I would worry the someObjects variable only contains a promise, so the session would be disposed when it's actually resolved by s.ToList().
Admin
I know nothing about group joins in C# beyond the Google I did just now, but depending on the implementation, I could imagine that there could be a significant performance advantage in having the list of inner results sorted by primary key, especially if the runtime knows they are sorted by primary key.
Admin
The runtime wont know they are sorted by primary key. List doesn't contain anything to indicate how it is sorted, just the records themselves already sorted.
Admin
One more thought about that "inner" LINQ query. The primary key of a table should already be unique. None of the subsequent sorts (ThenBy) would do anything, except make for a more complicated expression. There is a lot of misunderstanding here.
Admin
Was going to say what many have said: In the line var sList = s as IList<SomeObjects> ?? s.ToList();
the part "s as IList<SomeObjects>" tries to cast s as an IList<SomeObjects> if it can it returns it, if it can't it returns null. If s can't be cast as an IList it then calls the ToList function on the base object which creates an entire new List and copies all the entries into that list.
If it only called ToList it would be a memory waste if the original object already was a list.
With this the final variable is then known to be an ILIst for sure wether the original was just a iEnumerable or a List or even an IQueryable object.
Admin
Add me to the crowd that sees a legitimate case here--this is a trap for s being something other than the expected type.
I strongly suspect this is covering up a bug somewhere else, though.
Admin
True, dat. And if you use Entity Framework, or even Non-Borked Object Relational Mapping, you won't see a problem.
If you're asking for a set with a primary key, you'll get a set with appropriate sorting. Otherwise, what would the primary key be for?
Then again, I'll just be #94 in the list to point out that there's nothing wrong in C# with testing an "as" assertion against a null. Under certain circumstances ... what am I saying, ALL CIRCUMSTANCES ... this is quite the thing to do.
Unless, obviously, your priority is TBX (test by exception).
Admin
Both Remy and Abbie, it seems.
Really, I don't know C# at all, but even I figured that much by analogy with C++'s dynamic_cast.
As for the sorts, I'd have thought that the latter ones don't matter since the primary key is (yeah, should be) unique already. Maybe the first one doesn't matter either, though as stated.
So let's call it a draw between the submission and the description in WTFiness.
Admin
I'm not too familiar with LINQ, but isn't "s" (someObjects) already specifically a List<SomeObjects>, not just an IEnumerable<SomeObjects>? It's declared as such, and set to session.Query().blablabla.ToList() in the preceding code.
Admin
Ahh... this explains much of the codebase I’ve been working with recently. The Scala
asInstanceOf[SomeClass]
operator does not returnnull
on a failed cast - but clearly my predecessor had come from a C# background.Admin
I don't know if I'm right or wrong here, but I didn't think you could compare an IEnumerable to sort by it?
Addendum 2020-12-01 05:04: No wait... I read the code wrong. Don't flame me for being an idiot, I just posted prematurely.
Admin
One thing I do know is that the .NET runtime is definitely NOT that smart.
Admin
How is this a check for s being equal to null? It checks if s is an IList. Else, it tries to make a list of it.