2013-10-22 28 views
4

這個單語句查詢很整潔地說:「給我一個文件名爲包含特定文件結構的ZIP存儲庫的文件名列表。」如何使用一致的語法重寫此LINQ表達式?

但我同時使用.Where()擴展方法(流暢的語法)和一個選擇查詢,因爲我嘗試其他任何事情都無法編譯。如果我將「Where(文件==> <語句>)」更改爲「<語句>」,則會出現匿名方法代碼不會返回bool的錯誤,並且如果更改「選擇<子句>」到「。選擇(<子句>)」,錯誤是「沒有使用select子句」。

我很高興與查詢或流利的語法,但我想解決一個或另一個。任何人都可以解釋爲什麼這不起作用,我需要做什麼來解決一個一致的語法?

return (from file in Directory.EnumerateFiles(
        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Globals.CompanyName, ProjectName, FolderName), 
        imageExtension, 
        SearchOption.TopDirectoryOnly) 
    .Where(file => 
    { 
     try 
     { 
      string relativePath = ClassFru.Station + "/"; // Inside ZIPs, paths use a single forward slash 
      var zip = new ZipFile(); 
      zip.ZipError += (s, o) => { throw new Exception(); }; 
      using (zip = ZipFile.Read(file)) 
      { 
       /// <todo>if (zip.Comment != Globals.CompanyName) { return false; }</todo> 
       foreach (var fru in this.gFrus) 
       { 
        var fruPath = relativePath + fru.Id + '.'; 
        if (!(from e in zip where !e.IsDirectory && e.FileName.StartsWith(fruPath) select true).Any()) { return false; } 
       } 
       return true; 
      } 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    }) 
    select Path.GetFileNameWithoutExtension(file)).ToArray(); 
+0

我認爲這可能是其中幾個'foreach'列舉更容易理解的情況之一:) –

+4

那個'Where'的內容幾乎肯定不應該是一個匿名方法;這應該是一個命名方法,以便您可以編寫像'.Where(DirectoryIsValid)'或類似的東西。 – Servy

+0

你得到「不使用select子句」的原因是因爲你也有'from'。將整個東西轉換爲方法語法,或者像Servy所說的那樣將lambda提取到方法中。 –

回答

3

因爲我不知道你在使用這個表達式是挺難編譯它,但所有類型的,我認爲我應該像那:

  return (Directory.EnumerateFiles(
      Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), 
       Globals.CompanyName, ProjectName, FolderName), 
      imageExtension, 
      SearchOption.TopDirectoryOnly) 
      .Where(file => { 
       try 
       { 
        string relativePath = ClassFru.Station + "/"; // Inside ZIPs, paths use a single forward slash 
        var zip = new ZipFile(); 
        zip.ZipError += (s, o) => { 
         throw new Exception(); 
        }; 
        using (zip = ZipFile.Read(file)) 
        { 
         /// <todo>if (zip.Comment != Globals.CompanyName) { return false; }</todo> 
         foreach (var fru in this.gFrus) 
         { 
          var fruPath = relativePath + fru.Id + '.'; 
          if(zip.Any(e=> !e.IsDirectory && e.FileName.StartsWith(fruPath)) 
            .Any()) 
          { 
           return false; 
          } 
         } 
         return true; 
        } 
       } catch (Exception) 
       { 
        return false; 
       } 
      }).Select(Path.GetFileNameWithoutExtension).ToArray()); 
+0

很好的答案,非常感謝你,但是我最喜歡這個,因爲它實際上給出了簡潔的工作代碼,沒有典型的(ha!)宗教戰爭。代碼WAS的原始版本使用命名方法,但因爲查詢是大型方法的一部分,所以它將實現與引用分離了很長距離。對我來說,這更好,因爲它說我想在一個地方。 – shipr

1

除了改變使用selectSelect(file =>您還需要在開始時刪除from file in。然後,您將刪除使用該查詢語法select子句。這是唯一的from子句導致了你所看到的錯誤。每個from [...] in子句都需要匹配select

+0

+1我不知道爲什麼我以前從未注意到,當我看到。選擇)我沒有看到從條款。我總是發現查詢語法更具可讀性,但我慢慢學習的不同。 – shipr

0

我很高興與查詢或流利的語法,但我想解決一個或另一個。任何人都可以解釋爲什麼這不起作用,我需要做什麼來解決一個一致的語法?

它不適合你,因爲LINQ並沒有真正處理複雜邏輯的大塊作爲條件。特別是,LINQ Expression語法假設您將提供表達式(而不是塊),因此它不直接支持多行語句。

如果您只是刪除from部分的查詢,您可以很容易地獲得方法語法,如ISun shows you how to do

另一方面,如果您只是簡單地提取匿名方法,您的代碼將更容易理解和模塊化,正如@Servy在評論中所建議的那樣。在這種情況下,你可以決定說where FileHasMatchingZipStructure(file)。或.Where(FileHasMatchingZipStructure),如你所願。