85

As I was writing some extension methods for my business logic objects, I came to the question of renaming the conversion methods. someObject.ToAnotherObject() would go fine with the widely used object.ToString().

However LINQ, for example, mixes up both variants and I can't find a difference between them. ToDictionary(), ToList(), AsParallel(), AsQueryable(), ...

What are the differences between these two naming conventions and what should I know to decide whether to use for my own classes?

kerem
  • 2,699
  • 1
  • 32
  • 37
Physikbuddha
  • 1,652
  • 1
  • 15
  • 30

2 Answers2

94

ToDictionary and ToList are prefixed with To because they don't necessarily preserve the structural identity of the original collection or its properties.

  • Transforming a List<T> into a Dictionary<K, V> creates a collection with a whole new structure.
  • Transforming a HashSet<T> into a List<T> removes the uniqueness property of sets.

Methods prefixed with As don't do any of these things - they simply provide an alternative view of the original collection. They enrich it.

dcastro
  • 66,540
  • 21
  • 145
  • 155
  • 42
    So, on an apple I could call `.AsCleanApple()` since I only need to wash it, and `.ToFruitSalad()` because my knife would change the structure of the apple‽ – Physikbuddha Aug 07 '15 at 11:21
  • 3
    @Physikbuddha Basically, yes. – MKII Aug 07 '15 at 11:35
  • 38
    @Physikbuddha It seems to me like `AsCleanApple` will *change* something about the apple. A better analogy might be `AsFruit` – dcastro Aug 07 '15 at 11:39
  • 4
    `.AsCleanAppleSource()` would turn something that was a source of apples into something that was a source of clean apples; adding a washing step if necessary but perhaps doing nothing it the apples were already known to be clean. `.ToPunnet()` would access that source and give you a punnet of apples. – Jon Hanna Aug 07 '15 at 12:06
  • 3
    This is not strictly true, but in general you can think of "AsXXX()" as a cast and "ToXXX()" as a conversion. – nateirvin Aug 13 '15 at 19:19
  • If I'd transform a IEnumerable to IEnumerable where T can implicitly be cast into T, would that be a ToU or AsU? Or would that depend on whether I do or do not actually enumerate the input in my method? `foreach (var t in input) yield return t` When someone enumerates the result of my method, the implicit cast will create new instances of U for each item. I'm having a hard time determining if I would be changing the "structural identity" of the IEnumerable. – comecme May 27 '20 at 15:15
26

In Linq, the ToXXX methods all execute the query and create a new object from the results, while the AsXXX methods produce a new query which is different in some way. It may be the same object but accessed through a different interface (AsEnumerable() does this) or it may be a new object that alters the functionality (the other methods do this, though some check to see if they can just return the given object, e.g. AsQueryable() will return source if it implements IQueryable<T> already, or create a new EnumerableQuery<TElement> otherwise).

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • `that alters how the functionality` - Is `how` unnecessary or should there be a next part of the statement? – Kapol Aug 07 '15 at 16:48
  • @Kapol no, just a typo caused by composing and typing at the same time. – Jon Hanna Aug 07 '15 at 17:07
  • I think this is the correct answer, i.e. an active versus static projection of the original instance. `ToXXX()` projects the data with no relationship to the original. `AsXXX()` maintains an active relationship to the original (at least in the Enumerable/Queryable examples we're discussing). – Tim M. Aug 07 '15 at 20:31
  • +1 for `ToXXX execute the query` and `AsXXX produce a new query`. Sounds right from what I've read on LINQ, and [MSDN seems to confirm for ToXXX](https://msdn.microsoft.com/en-us/library/bb882641.aspx), but I am wondering if anyone has a source for whether *all* `AsXXX` methods are deferred execution? – brichins Aug 12 '15 at 04:59
  • 1
    @brichins is there even a meaningful way to say "all" given that any one of us could come along with a new provider that adds a new `AsXXX` on top of those inherent to Linq (e.g. the `AsParallel` added by PLinq, the `AsNoTracking` provided by Entity Framework, and so on). Certainly, the core of linq is what is defined by `Queryable` and `Enumerable`, and those two classes both follow that convention. Most additions do to, to the extent that "all" would probably be correct, but it's too open to be guaranteed to always be correct (though I would consider any break a design flaw). – Jon Hanna Aug 12 '15 at 08:50
  • @JonHanna Excellent point about multiple or custom providers - I was imagining "all" to be the core LINQ functionality, which you called out and addressed specifically. Verifying for each provider is beyond the scope of this question, so that is exactly the answer I was looking for. – brichins Aug 13 '15 at 14:41
  • @brichins well, one of the methods mentioned in the question is outside of the narrowest definition of what the core of linq is, viz `AsParallel`. It does also follow the same naming convention though. – Jon Hanna Aug 13 '15 at 14:46