Is using LINQ against a single object considered a bad practice?
c#, linq
Solution
I say yes, but it's really up to preference. It definitely has disadvantages, but I will leave that up to you. Your original code can become much simpler though.
string cfg = ConfigurationManager.AppSettings["myKey"];
decimal bla;
if (!decimal.TryParse(cfg,out bla) || bla < 0 || bla > 10)
bla = 0; // 0 is the default value
This works because of "short circuit" evaluation, meaning that the program will stop checking other conditions once the first true condition is found.
Problem
I don't mean this question to be too subjective. I google'd this for some time but got no specific answers to address this issue. The thing is, I think I'm getting somewhat addicted to LINQ. I already used LINQ to query on lists among other things like using Linq to Sql, Xml, and so on. But then something struck me: "What if I used it to query a single object?" So I did. It may seem wrong like trying to kill a fly with a grenade launcher. Though we all agree it would be artistically pleasant to see. I consider it very readable, I don't think there is any performance issues regarding to this, but let me show you an example. In a web application, I need to retrieve a setting from my configuration file (web.config). But this should have a default value if the key is not present. Also, the value I need is a decimal, not a string, which is the default return from `ConfigurationManager.AppSettings["myKey"]`. Also, my number should not be more than 10 and it should not be negative. I know I could write this: ``` string cfg = ConfigurationManager.AppSettings["myKey"]; decimal bla; if (!decimal.TryParse(cfg,out bla)) { bla = 0; // 0 is the default value } else { if (bla<0 || bla>10) { bla = 0; } } ``` Which is not complicated, not convoluted, and easy to read. However, this is how I like it done: ``` // initialize it so the compiler doesn't complain when you select it after decimal awesome = 0; // use Enumerable.Repeat to grab a "singleton" IEnumerable<string> // which is feed with the value got from app settings awesome = Enumerable.Repeat(ConfigurationManager.AppSettings["myKey"], 1) // Is it parseable? grab it .Where(value => decimal.TryParse(value, out awesome)) // This is a little trick: select the own variable since it has been assigned by TryParse // Also, from now on I'm working with an IEnumerable<decimal> .Select(value => awesome) // Check the other constraints .Where(number => number >= 0 && number <= 10) // If the previous "Where"s weren't matched, the IEnumerable is empty, so get the default value .DefaultIfEmpty(0) // Return the value from the IEnumerable .Single(); ``` Without the comments, it looks like this: ``` decimal awesome = 0; awesome = Enumerable.Repeat(ConfigurationManager.AppSettings["myKey"], 1) .Where(value => decimal.TryParse(value, out awesome)) .Select(value => awesome) .Where(number => number >= 0 && number <= 10) .DefaultIfEmpty(0) .Single(); ``` I don't know if I'm the only one here, but I feel the second method is much more "organic" than the first one. It's not easily debuggable, because of LINQ, but it's pretty failproof I guess. At least this one I wrote. Anyway, if you needed to debug, you could just add curly braces and return statements inside the linq methods and be happy about it. I've been doing this for a while now, and it feels much more natural than doing things "line per line, step by step". Plus, I just specified the default value once. And it's written in a line which says `DefaultIfEmpty` so it's pretty straightforward. Another plus, I definitely don't do it if I notice the query will be much larger than the one I wrote up there. Instead, I break into smaller chunks of linq glory so it will be easier to understand and debug. I find it easier to see a variable assignment and automatically think: this is what you had to do to set this value, rather than look at ifs,elses,switches, and etc, and try to figure out if they're part of the formula or not. And it prevents developers from writing undesired side effects in wrong places, I think. But in the end, some could say it looks very hackish, or too arcane. So I come with the question at hand: Is using LINQ against a single object considered a bad practice?