7

我有一個使用迭代器塊一個簡單的方法返回一個IEnumerable<T>問題,使用C#迭代方法

IEnumerable<MyItem> GetItems() 
{ 
    foreach (var item in Items) 
    { 
     yield return item; 
    } 
} 

通常情況下,這種方法效果很好,但如果我申請一個[SecurityCritical]屬性的程序集(或者包含上述方法的類),它會在嘗試調用方法時拋出TypeLoadException。未能加載的類型是編譯器生成的類,它對應於迭代器方法,並且它是導致該問題的方法,因爲它是安全透明的。

作爲比較,如果我修改上述方法,以便它填充並返回List<MyItem>,一切工作正常。

有什麼建議嗎?

謝謝,

Tim。

+0

也許`[SecurityCritical]`試圖告訴你不要使用`var`並且是更多類型特定的? – BeemerGuy 2010-11-25 14:24:03

回答

3

這不是最好的事情,所以希望你可以找到更好的方法,但你總是可以放棄編譯器生成的代碼並創建自己的類來實現IEnumerator<MyItem>(也許你自己的類實現了IEnumerable<MyItem> - 取決於複雜性,這樣做可能會讓事情變得更容易或更困難),然後像在.NET2.0之前的日子那樣或多或少地構建枚舉器。

如果真正的迭代器塊的邏輯非常複雜,您可能會發現查看編譯器爲您創建的類的反射是一個很好的起點,儘管有時生成的代碼更復雜(或者至少不太可讀)比人們自己的方法。

yield在99%的時間裏對我們非常好,但是仍然有它需要的時候,它可能會解決你的問題,但是要建立一個IEnumerator課總是有點令人失望。

3

我在複雜的應用程序中遇到了同樣的問題。 Spring之間進來說,'blahblah'類型不是Serializable,並確定它是正確的,下面是編譯器生成代碼的反彙編代碼,並確保它不是Serializable。也許這也是你的問題,而解決辦法就是你自己提到的,因爲List實際上是一個Serializable類型。

的代碼生成yield return new KeyValuePair<??? ???>(???,???);

[CompilerGenerated, DebuggerDisplay(@"\{ x = {x}, y = {y} }", Type="<Anonymous Type>")] 
internal sealed class <>f__AnonymousType0<<x>j__TPar, <y>j__TPar> 
{ 
    // Fields 
    [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    private readonly <x>j__TPar <x>i__Field; 
    [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    private readonly <y>j__TPar <y>i__Field; 

    // Methods 
    [DebuggerHidden] 
    public <>f__AnonymousType0(<x>j__TPar x, <y>j__TPar y) 
    { 
     this.<x>i__Field = x; 
     this.<y>i__Field = y; 
    } 

    [DebuggerHidden] 
    public override bool Equals(object value) 
    { 
     var type = value as <>f__AnonymousType0<<x>j__TPar, <y>j__TPar>; 
     return (((type != null) && EqualityComparer<<x>j__TPar>.Default.Equals(this.<x>i__Field, type.<x>i__Field)) && EqualityComparer<<y>j__TPar>.Default.Equals(this.<y>i__Field, type.<y>i__Field)); 
    } 

    [DebuggerHidden] 
    public override int GetHashCode() 
    { 
     int num = -576933007; 
     num = (-1521134295 * num) + EqualityComparer<<x>j__TPar>.Default.GetHashCode(this.<x>i__Field); 
     return ((-1521134295 * num) + EqualityComparer<<y>j__TPar>.Default.GetHashCode(this.<y>i__Field)); 
    } 

    [DebuggerHidden] 
    public override string ToString() 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.Append("{ x = "); 
     builder.Append(this.<x>i__Field); 
     builder.Append(", y = "); 
     builder.Append(this.<y>i__Field); 
     builder.Append(" }"); 
     return builder.ToString(); 
    } 

    // Properties 
    public <x>j__TPar x 
    { 
     get 
     { 
      return this.<x>i__Field; 
     } 
    } 

    public <y>j__TPar y 
    { 
     get 
     { 
      return this.<y>i__Field; 
     } 
    } 
} 
0

您可以投票給這個問題:https://connect.microsoft.com/VisualStudio/feedback/details/667328/yield-and-securitycriticalattribute-problem

從微軟

[編輯]回覆:

我們已經看了SecurityCritical迭代器和決定不要嘗試 至少在此版本中起作用。這是一項重大的工作,並且看起來不太有用,因爲通過IEnumerator.MoveNext的呼叫 將通過非關鍵的 接口進行呼叫。

我們可能會在以後的版本中再次訪問這個;特別是如果我們 看到它的常見情況。