Lambda变量名称 – 短名称,还是不短名称?

通常,当我使用lambdas时,我只使用“a,b,c,d ……”作为变量名称,因为类型很容易推断,我发现短名称更容易阅读。 这是一个例子:

var someEnumerable = GetSomeEnumerable(); var somethingElseList = someEnumerable.Select(a => a.SomeProperty) .OrderBy(a => a.SomePropertyField); var someDictionary = somethingElseList.ToDictionary(a => new SomeClass(a.Prop1), a => a); 

有人质疑这个命名,并且更愿意看到长输出的名称,如下所示:

 var someEnumerable = GetSomeEnumerable(); var somethingElseList = someEnumerable.Select(importantObj => importantObj.SomeProperty) .OrderBy(objsInfo => objsInfo.SomePropertyField); var someDictionary = somethingElseList.ToDictionary(theInfoId => new SomeClass(theInfoId.Prop1), theInfoId2 => theInfoId2); 

由于范围很窄(在parens之间),除非你变得愚蠢并将它们嵌套,否则我会发现阅读短名称更容易。

我没有被上面使用的愚蠢的命名示例所吸引,对Lambda变量名称的一般共识是什么? 要简短的名字,还是不要简短的名字?

我通常这样做的方式取决于你所列举的集合。 如果集合的名称暗示lambda参数将是什么类型,那么我只使用单个字母,但是如果集合不是描述性的,那么我将使用一个单词。

IE:

 myCollection.Where(person =>....); //non descriptive collection name myPeopleCollection.Where(p=>...); // descriptive collection name 

我尝试使用单字但有意义的名字。 所以我倾向于使用“人”而不是“p”,但不会选择“newAddedPerson”。

这也适用于查询表达式 – 我可能会在快速一次性的例子中违反这一点,但我通常不喜欢:

 from p in source where p.Age > 10 select p.Name; 

我宁愿看到

 from person in source where person.Age > 10 select person.Name; 

我喜欢这个简称。 我一直这样做。 我主要在lambdas中使用i,y,x,但我在sql中使用a,b,c,d。

我会说我同意BFree。 对我而言,这取决于具体情况,但我总是试图尽可能“简洁”。 请注意,我说简洁,而不是简洁或简短。

以下是LISP方言Clojure中的两个例子:

 user=> (def names ["ryan" "bob" "tom" "tim"]) #'user/names user=> (filter (fn [name] (.startsWith name "t")) names) ("tom" "tim") 

对于那些不了解Lisp / Clojure的人,我的lambda是函数’filter’的参数。 也就是说,“(fn [name] ….)”。 我选择在这里使用’name’,因为它很简短,但我确切地描述了我正在使用的内容。 但是,我认为’a’,’i’,’x’等同样可读。

 user=> (def odds (iterate (fn [n] (+ n 2)) 1)) #'user/odds user=> (take 5 odds) (1 3 5 7 9) 

在这里,我只使用’n’代表’数字’。 我认为“数字”也可以,但对我的口味来说有点过于冗长。

我当然不会使用名称’nameOfPerson’或’previousOddNumber’。 这只是太多的信息。 我也尝试在大多数时候保留我的名字,例如’nameString’。 在大多数情况下,我发现这样的东西是多余的信息。

就个人而言,我认为像这样的额外冗长的名称往往源于它有助于记录代码的想法。 它似乎在Java / C#等语言中尤为普遍。 我认为这可以通过两种方式进行争论,具体取决于程序员的风格。 但是,名称越详细,代码就越紧(读得脆弱)。 如果我的名字非常具体,并且它的function经常发生变化,那么名称也可能会发生很大的变化。 最终,DEV可能会变得懒惰,并且您最终会得到一个名称,该名称实际上并未描述变量的用途。 当且仅当程序员不认为名称正确时,这不是问题。 当然,这可能会在编译期间很快被弄清楚(因为程序员会尝试划分两个字符串或某些这样的东西),但它可能会导致浪费时间和大型项目中的混乱。

我也会因为屏幕不动产而争论简洁。 我仍然试图将我的行包裹在80列宽,当’myVaraibleNameIsAsLongAsAParagraph’时这很难。

最终,我认为它总是会达成妥协。 所以他们不喜欢’a’,但也许他们可以同意你应该争取像’人’或’数字’这样的单词名称,并避免那种可怕的骆驼案例。

对不起,这本书。

我们的团队不允许使用单字母变量,而不允许使用lamdas中的事件。

我们发现,就像在TSQL中一样,代码存在的时间越长,它就会越混乱。 就lambda而言

我们会这样做:

 people.Where(personFound => personFound.FirstName.Contains("blah!")); 

那样下一个开发者就不用看了

 people.Where(p => p.FirstName.Contains("blah")); 

它似乎是可读的,但它一开始总是这样

加入怎么样?

 citizenShip.Join(people, c => c.personid, p => p.persoinid, (p, c) => new { p.FirstName, c.IsCitizen}) .Where(pc => pc.FirstName.Contains("blah"); 

与变量名称相同

 citizenShip.Join(people, citizenToJoin => citizenToJoin.personid, personToJoin => personToJoin.persoinid, (joinedPerson, joinedCitiznship) => new { joinedPerson.FirstName, joinedCitiznship.IsCitizen}) .Where(personAndCitizenshipFound=> personAndCitizenshipFound.FirstName.Contains("blah"); 

哦,但这很令人困惑和丑陋。 只需使用不同的字母,这样就不那么容易混淆了

 citizenShip.Join(people, c => c.personid, p => p.persoinid, (jp, pc) => new { jp.FirstName, jc.IsCitizen}) .Where(pc => pc.FirstName.Contains("blah"); 

仍然令人困惑,但现在情况更糟。 所以我们打破了lambda,所以我们重构为了可读性

 var peopleWithCitizenship = citizenShip.Join(people, citizenToJoin => citizenToJoin.personid, personToJoin => personToJoin.persoinid, (joinedPerson, joinedCitiznship) => new { joinedPerson.FirstName, joinedCitiznship.IsCitizen}); var peopleWithCitizenshipFilteredByName = peopleWithCitizenship.Where(personAndCitizenshipFound=> personAndCitizenshipFound.FirstName.Contains("blah")); 

这不是一个完美的例子,但是使用非常少的内幕知识使代码可读。 我们发现这暴露了复杂的代码(lambda),它需要分解成更小的块。

可能要求很多人就“命名”提出“共识”问题。 🙂

我同意“好名字的重要性”与名称的范围成正比。 Jon Skeet的偏好回答

 from person in source ... 

是令人信服的,但如果名称被大量使用,特别是如果输入更好地命名,我想我更喜欢

 from p in persons ... 

我使用一个,两个或三个字母,这些字母形成了相关对象的缩写表示。

 Persons.Where(p => ...) AnalysisCode.Where(ac => ...) 

作为一般规则,我认为变量/对象/方法名称越明确越好。 由于我们经常花大部分时间阅读其他人的代码,因此我们更容易理解,您可以更快地将注意力集中在语法和逻辑上。 这些天使用IntelliSense等,尽可能在清晰度方面犯错并不是真正的负担。

我同意@Johnny Wey; 命名您的变量 – 出于同样的原因,您可以在任何其他代码中命名它们! 由于代码的“内联”特性,不要理解这种远离清晰度的偏好。 可读性是关键 – 一目了然/不需要“hover”过东西; 否则,你可能会说没有变量需要适当命名。 如果使用“Enuerable”的东西可能有点余地,但仍然很高兴看到(再次一目了然)代码正在做什么。 如果变量类型推断依赖于传递给类或类似物的某些generics类型,请来命名。 将所有代码读成句子; 计算机应该适应我们(“人性化”),而不是相反,我们开始像计算机一样行动并且变得神秘,因为我们可以/感觉更聪明/更像技术极客当我们这样做(诱惑在那里,我硝酸钾!)。 输入一个清晰的名称很容易,你仍然拥有在命名方法中所做的所有Intellisense /句子完成选项。 另外,在lambdas的情况下徘徊并不总是给你关于var的信息(在调试期间令人沮丧),所以很高兴看到“清楚/有代表性”的命名,特别是对于没有通过所有心理体操的新开发者而言能够通过遍历语句上下文(也可能是神秘的)来推断类型。

如果变量的目的明确,则缩短更好。 Lambdas需要一种function性的写作风格,因此你会在一行中看到很多链接。 它更清洁,看你什么时候保持它们。

另一种情况是,有时您需要声明一个在该范围内没有相关性/含义的虚拟变量。 在这种情况下,我使用_ ,这让我很清楚。 这在方法重载期间尤其方便,例如,

 public Foo Do() { return Do(_ => true); } public Foo Do(Func pattern) { return SomethingElse(pattern); } 

基于上面的答案,我认为普遍的共识是,如果你无法从上下文中判断出你在处理什么,使用描述性名称会更好。 例如:

 entities.Where(person => person.Age >= 21); 

但是,在上下文显而易见的情况下,单个字母的名称实际上可能有助于提高可读性,因为它可以更容易地关注关键信息。 例如:

people.Where(p => p.Age >= 21);people.Where(x => x.Age >= 21);

问题是,哪个更好, p还是x

  • 支持p ,它是SQL查询中熟悉的模式,并提供一些额外的提示,表明您正在谈论一个Person
  • 支持x ,如果将Person重命名为Customer ,则无需担心修复所有lambda参数。 如果您使用了p ,那么如果您的代码成为customers.Where(p => p.Age >= 21) ,那么实际上会有点混乱,而x基本上是不可知的。

我最近开始使用x ,到目前为止,我没有注意到任何明显的缺点,但如果你不同意,请发表评论。