2
\$\begingroup\$

While working on a project with a friend of mine, I noticed the following syntax:

public IObservable<X> GetXs()
{
    return from x in xs
           select x;
}

He said that while xs is an IObservable<X> field, this is the way it is supposed to be written in Linq, and everyone does it this way. It also allows one to add where-clauses later on easily.

On the other hand, Reflector shows that a new delegate is created that is passed to the Select() function on the observable, but that function always returns just this, so it seems to me it also has a slight overhead.

So I don't agree with him and would have written it as follows:

public IObservable<X> GetXs()
{
    return xs;
}

Are there any other reasons for using the from select-syntax without filtering, selecting or ordering that I might have missed? Which syntax is better and why?

\$\endgroup\$
2
\$\begingroup\$

I don't personally use RX, so my answer may be wrong, but he is it anyway:

I don't know whether “everyone does it this way”, but I doubt it. The code is translated into (after LINQ query transformation and by writing extension method invocation as if it was a normal method):

return Observable.Select(xs, x => x);

Observable.Select does exactly what you would expect it to, if you know LINQ to objects: it creates a new observable, which consumes each item from xs, processes it using the delegate you gave it (which in this case just returns the item unchanged) and then produces the result.

So, using that code does have some overhead, but it will be most likely negligible for you and you shouldn't worry about it much. But it does make the code longer and more confusing (it did confuse you). And “there is a chance it will save you some typing in the future” is not a good reason to sacrifice readability, I think.

\$\endgroup\$
0
\$\begingroup\$

Many rules which "always" apply or tell you to "never" do something should not be taken literally. Nothing is always true.

The only thing that a "null query" does is to prevent access to the underlying collection. This is a valid goal, but it seems unnecessary in your case.

You should add complexity when it is required, not by default.

\$\endgroup\$
-1
\$\begingroup\$

Based on my understanding the first option is going to create a whole new enumerable object (as well as a linq iterator object) as well as the overhead of calling a function for each element. I would definitely go with the second (your) option. If you need where filtering later, then add it later on.

This next part definitely applies when returning a type of IEnumerable, I can't say 100% for an IObservable, but that LINQ syntax is lazily evaluated. If the return value is NOT used right away but saved for later and the state of xs has changed when you go to use it you might get unexpected results if you don't force the evaluation right away after returning from the function.

\$\endgroup\$
3
  • \$\begingroup\$ It's not going to create new enumerable object or an iterator, because there is no IEnumerabble<T> in the method. The question is about IObservable<T>. \$\endgroup\$ – svick Mar 30 '12 at 16:19
  • \$\begingroup\$ Maybe I'm wrong... but I wouldn't think it matters what type of object is being returned. The LINQ syntax is being used to populate the collection, so in the execution of that method there will be some overhead of doing the LINQ. \$\endgroup\$ – schlechtums Mar 30 '12 at 16:38
  • \$\begingroup\$ But the type of the object is precisely what matters. The LINQ syntax here is not used to populate any collection, simply because there is no collection. And yes, it will probably have some overhead, but I think it will be negligible here, so I wouldn't base my decision on it. \$\endgroup\$ – svick Mar 30 '12 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.