我并不是说这个问题过于主观.
我已经谷歌了一段时间但没有得到解决这个问题的具体答案.问题是,我认为我对LINQ有点上瘾.我已经使用LINQ来查询列表,比如使用Linq到Sql,Xml等等.但后来有些事情让我感到震惊:"如果我用它来查询单个对象怎么办?" 所以我做了.试图用手榴弹发射器杀死一只苍蝇似乎有点不对劲.虽然我们都同意这看起来很艺术.
我认为它非常易读,我认为这方面没有任何性能问题,但让我举个例子.
在Web应用程序中,我需要从配置文件(web.config)中检索设置.但是如果密钥不存在,则应该有一个默认值.此外,我需要的值是十进制,而不是一个字符串,这是默认的返回ConfigurationManager.AppSettings["myKey"].此外,我的电话号码不应超过10,也不应该是负数.我知道我可以这样写:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这不复杂,不复杂,易读.但是,这就是我喜欢它的方式:
// 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();
Run Code Online (Sandbox Code Playgroud)
没有评论,它看起来像这样:
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();
Run Code Online (Sandbox Code Playgroud)
我不知道我是否是这里唯一的一个,但我觉得第二种方法比第一种方法更"有机".由于LINQ,它不容易调试,但我认为它非常防误.至少我写的这个.无论如何,如果你需要调试,你可以在linq方法中添加花括号和返回语句,并对它感到高兴.
我现在已经这样做了一段时间,并且感觉比"每行一行,一步一步"做事更自然.另外,我只指定了一次默认值.它写在一条线上,说它DefaultIfEmpty非常简单.
另外一个加号,如果我注意到查询会比我在那里写的要大得多,我绝对不会这样做.相反,我打破了较小的linq荣耀块,因此更容易理解和调试.
我发现更容易看到变量赋值并自动思考:这是你必须要设置的值,而不是查看ifs,elses,switch等,并试图弄清楚它们是否属于公式与否.
我认为它可以防止开发人员在错误的地方写下不受欢迎的副作用.
但最终,有些人可能会说它看起来非常hackish,或者说太神秘了.
所以我提出了手头的问题:
使用LINQ对单个对象被认为是一种不好的做法?
我说是的,但这真的取决于偏好.它肯定有缺点,但我会把它留给你.您的原始代码可以变得更简单.
string cfg = ConfigurationManager.AppSettings["myKey"];
decimal bla;
if (!decimal.TryParse(cfg,out bla) || bla < 0 || bla > 10)
bla = 0; // 0 is the default value
Run Code Online (Sandbox Code Playgroud)
这是因为"短路"评估,这意味着一旦找到第一个真实条件,程序将停止检查其他条件.