我在 Codewars 上解決了一個 C# 初學者 Kata,要求回傳一個只有 4 個字符的名稱的 string[]。我使用了一個在 if 陳述句中填充的串列,然后轉換回字串并回傳。
我的問題是關于下面的最佳實踐解決方案,稍后介紹。
我知道作為引數出現的相同 string[] 會重新填充元素并回傳。但是程式如何知道陣列的每個元素都被稱為“名稱”,因為它以前從未提到過?
linq 是否知道具有單數名稱的變數是復數名稱組的元素,這里是“名稱”?
感謝您的幫助!
using System;
using System.Collections.Generic;
using System.Linq;
public static class Kata {
public static IEnumerable<string> FriendOrFoe (string[] names) {
return names.Where(name => name.Length == 4);
}
}
uj5u.com熱心網友回復:
我知道作為引數出現的同一個 string[] 被重新填充元素并回傳
我將簡要說明這個問題,因為這不是您要問的問題。這不是真的 - 不會發生任何重新填充。原始陣列沒有改變,Where 是一個回圈,它運行在陣列上,并在提交給它的測驗對該專案評估為真時有選擇地從中發出專案。它這樣做的方式是通過一個稱為 a 的特殊結構yield return,它允許代碼從一個方法回傳,然后重新進入它并從它之前停止的地方繼續,而不是從頭開始重新開始方法。只有一個陣列,除非您從 Where 生成的一組字串開始讀取,否則不會執行回圈/測驗。如果您想了解更多資訊,請發表評論。
繼續..
linq 是否知道具有單數名稱的變數是復數名稱組的元素,這里是“名稱”?
不; IDE 知道該變數,name因為這是您選擇在Where(
也許將它與您已經知道的東西聯系起來會有所幫助。撰寫以下代碼是完全可以接受的:
public static class Kata {
public static IEnumerable<string> FriendOrFoe (string[] names) {
return names.Where(IsNameOfLengthFour);
}
static bool IsNameOfLengthFour(string name){
return name.Length == 4;
}
}
哪里需要提供一些接受字串并回傳布林值的方法。它要求輸入是一個字串,因為它被呼叫的names是一個字串陣列。如果它是陣列中的整數,則傳遞給 Where 的方法必須采用int
在 C# 中,通常會推動使事情更緊湊,因此為了擺脫上面的所有冗長,我們有一種更緊湊的撰寫方法體的形式。讓我們減少冗長的版本:
static bool IsNameOfLengthFour(string name){
return name.Length == 4;
}
我們可以去掉回傳型別,因為我們可以從回傳的型別中猜測出來。我們也可以擺脫靜態,如果我們從另一個靜態內部呼叫它,就假設它是靜態的,否則就假設不是。我們也可以放棄輸入型別,因為我們可以從輸入的型別中猜測出來。
IsNameOfLengthFour(name){
return name.Length == 4;
}
如果我們有一個只有一行的特殊語法并且必須是一個自動回傳的值,我們可以去掉return, 和{}因為它只有一行,所以我們不需要隔離多個陳述句:
IsNameOfLengthFour(name) => name.Length == 4
現在,如果我們要在某個名稱無關緊要的地方使用它,我們實際上不再需要方法名稱,而且我們實際上也不需要()單個引數:
name => name.Length == 4
這對于編譯器來說是足夠的運算式,能夠從中形成一個方法,并將其插入到期望方法接受字串并回傳布林值的東西中。我們已經拋棄了我們人類喜歡的方法的所有細節(名稱和識別符號),并只為編譯器提供了它需要的原始細節——方法的邏輯。編譯器將在為我們將它們連接在一起時重新創建其余的絨毛;我們永遠無法從代碼的其他地方呼叫這個小方法,但我們不在乎。我們得到了我們想要的,這是表達邏輯的一種很好的緊湊方式:
Where(n => n.Length==4);
你做得很好,把這個小方法的論點稱為合理的。我看到x使用了很多,當X發生變化時,它變得非常混亂。例如:
names
.Where(name => ...)
.GroupBy(name => ...)
.Select(g => g.First())
.Where(name => ...)
Where works on your array of names so calling the argument to the delegate name or n is a good idea. Where will filter it down but ultimately it still emits a set of strings that are names, so it's still a good idea to call it name on the way into a GroupBy.. But a GroupBy produces a set of IGrouping, not a set of string so the thing coming our of a GroupBy is no longer a name.. In the next Select I call it g to reflect that it's a grouping, not a name, but I then take the first item in the grouping which is, actually, a name.. So in the final Where I go back to calling the input argument name to reflect what it's back to being..
When LINQ statements get much more complicated, it really helps to name these arguments well
注意:在這個答案中,我使用了“list”或“set”之類的詞,我的意思是一般英語意義上的“陣列是 .. 的串列”,而不是特定的 C#List<xxx>或HashSet<xxx>意義。如果您看到與 C# 型別對齊的小寫單詞,則它們不打算指代該特定型別
uj5u.com熱心網友回復:
我知道作為引數出現的相同 string[] 會重新填充元素并回傳。
不,絕對不是。基于輸入陣列回傳一個全新的陣列。輸入陣列不會以任何方式修改或更改。
但是程式如何知道陣列的每個元素都被稱為“名稱”,因為它以前從未提到過?
name是匿名函式的引數。該name引數是基于背景關系的字串。這可以是x或ASDASDASD或任何你想要的,但我們在這里使用,name因為我們在每次呼叫時都有一個來自names.
因此,
names是傳遞給函式的字串陣列- 該
.Where回傳從當前陣列基于謂詞功能的新陣列(例如用于匹配回傳真,假省略) - 謂詞
name => name.Length == 4接受一個字串,如果字串長度為 4,則回傳 true - 函式的回傳是
names長度正好為 4 個字符的字串
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/383405.html
上一篇:linq從Id獲取值
