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的呼叫 将通过非关键的 接口进行呼叫。

我们可能会在以后的版本中再次访问这个;特别是如果我们 看到它的常见情况。