2009-06-08 90 views
2

在下面的代碼中,如何將myLine聲明爲公共(全局)變量?問題是我不能使用關鍵字「var」。如何使用匿名類型(C#)聲明字段

public static IEnumerable<string> ReadLines(StreamReader reader) 
    { 
     while (!reader.EndOfStream) 
     { 
      yield return reader.ReadLine(); 
     } 
    } 

    private void Filter1(string filename) 
    { 
     using(var writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
     { 
      using (var reader = File.OpenText(filename)) 
      { 
       int[] Ids = { 14652, 14653, 14654, 14655, 14656, 14657, 14658, 14659, 14660 }; 
       var myLine = from line in ReadLines(reader) 
          where line.Length > 1 
          let id = int.Parse(line.Split('\t')[1]) 
          where Ids.Contains(id) 
          let m = Regex.Match(line, @"^\d+\t(\d+)\t.+?\t(item\\[^\t]+\.ddj)") 
          where m.Success == true 
          select new { Text = line, ItemId = id, Path = m.Groups[2].Value }; 


       foreach (var id in myLine) 
       { 
        writer.WriteLine("Item Id = " + id.ItemId); 
        writer.WriteLine("Path = " + id.Path); 
        writer.WriteLine("\n"); 
       } 

      } 
     } 
    } 

我想這樣做,因爲我必須找到一種方法來獲得對該閏日的訪問權限以備後用。

+1

http://blogs.msdn.com/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx – 2009-06-08 16:22:25

回答

8

問題在於它使用了匿名類型,您不能在字段聲明中使用它。

修復方法是使用相同的成員編寫一個指定類型,並在查詢中使用該類型。如果你希望它具有相同的行爲,你的匿名類型,它應該:

  • 拿在構造函數中的所有值
  • 是一成不變的,露出只讀屬性
  • 覆蓋EqualsGetHashCodeToString
  • 密封

可以只使用反射來反編譯的代碼,而T3如果你最終會得到一個你並不需要的泛型類型。

類看起來是這樣的:

public sealed class Foo 
{ 
    private readonly string text; 
    private readonly int itemId; 
    private readonly string path; 

    public Foo(string text, int itemId, string path) 
    { 
     this.text = text; 
     this.itemId = itemId; 
     this.path = path; 
    } 

    public string Text 
    { 
     get { return text; } 
    } 

    public int ItemId 
    { 
     get { return itemId; } 
    } 

    public string Path 
    { 
     get { return path; } 
    } 

    public override bool Equals(object other) 
    { 
     Foo otherFoo = other as Foo; 
     if (otherFoo == null) 
     { 
      return false; 
     } 
     return EqualityComparer<string>.Default.Equals(text, otherFoo.text) && 
     return EqualityComparer<int>.Default.Equals(itemId, otherFoo.itemId) && 
     return EqualityComparer<string>.Default.Equals(path, otherFoo.path); 
    } 

    public override string ToString() 
    { 
     return string.Format("{{ Text={0}, ItemId={1}, Path={2} }}", 
          text, itemId, path); 
    } 

    public override int GetHashCode() 
    { 
     int hash = 17; 
     hash = hash * 23 + EqualityComparer<string>.Default.GetHashCode(text); 
     hash = hash * 23 + EqualityComparer<int>.Default.GetHashCode(itemId); 
     hash = hash * 23 + EqualityComparer<string>.Default.GetHashCode(path); 
     return hash; 
    } 
} 

您的查詢將只在最後更改爲:

select new Foo(line, id, m.Groups[2].Value) 
+0

基本上我爲每個ItemId做一個Foo類的實例,對嗎? 還有一個問題如果我可以問你,你爲什麼要宣佈他們是私人的?幾個月前,您教會我將其聲明爲公共字符串文本{get; private set}; – 2009-06-08 11:13:47

+0

這是用公共getter和私人setter聲明*屬性*。在這裏,我們已經獲得了屬性的公共getter,根本沒有* setter和私人領域。我更喜歡在可能的情況下完全只讀的課程。 – 2009-06-08 11:17:35

+0

哦,我忘了最重要的事情。使用你的代碼的IEnumerable類型是什麼? IEnumerable ? – 2009-06-08 11:21:59

2

而不是使用與鍵盤匿名類的,定義類顯式地使用Text,ItemId等。然後類型將是IQueryable <MyClass>。使用該代替var關鍵字。