使用具有代码访问安全性的C#迭代器方法时出现问题

使用具有代码访问安全性的C#迭代器方法时出现问题,c#,iterator,code-access-security,yield-return,typeloadexception,C#,Iterator,Code Access Security,Yield Return,Typeloadexception,我有一个简单的方法,它使用迭代器块返回一个IEnumerable: IEnumerable GetItems() { foreach(项目中的var项目) { 收益回报项目; } } 通常,此方法工作正常,但如果我将[SecurityCritical]属性应用于程序集(或包含上述方法的类),则在尝试调用该方法时会抛出TypeLoadException。未能加载的类型是编译器生成的类,该类对应于迭代器方法,而导致问题的是它的GetEnumerator方法,因为它是安全透明的 为了比较,如果我修改

我有一个简单的方法,它使用迭代器块返回一个
IEnumerable

IEnumerable GetItems()
{
foreach(项目中的var项目)
{
收益回报项目;
}
}
通常,此方法工作正常,但如果我将
[SecurityCritical]
属性应用于程序集(或包含上述方法的类),则在尝试调用该方法时会抛出
TypeLoadException
。未能加载的类型是编译器生成的类,该类对应于迭代器方法,而导致问题的是它的
GetEnumerator
方法,因为它是安全透明的

为了比较,如果我修改上述方法,使其填充并返回一个
列表
,则一切正常

有什么建议吗

谢谢


Tim.

这不是最整洁的事情,所以希望您能找到更好的方法,但您可以放弃编译器生成的代码,创建自己的类来实现
IEnumerator
(可能是您自己的类实现了
IEnumerable
——根据复杂性,这样做可能会使事情变得更容易或更困难),然后像在.NET2.0之前那样或多或少地构建枚举器

如果实际迭代器块的逻辑非常复杂,您可能会发现查看编译器为您创建的类的反射是一个很好的起点,尽管有时生成的代码比您自己所采用的方法更复杂(或至少可读性更低)


yield
让我们99%的时间都很满意时,构建
IEnumerator
类总是有点让人失望,但是仍然有一些时候它是必要的,它可能会解决您的问题。

在一个复杂的应用程序中,我也遇到了同样的问题。Spring介于两者之间,说hblah的类型不可序列化,请确保它是正确的,这是编译器生成的代码的反汇编代码,并且确保它不可序列化。可能这也是您的问题,解决方案就是您自己提到的,因为列表实际上是可序列化的类型

生成的代码返回新的KeyValuePair(???,??);

[CompilerGenerated,DebuggerDisplay(@“{x={x},y={y}”,Type=”“)]
内部密封类f__匿名类型0
{
//田地
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
专用只读j_u_uTPAR i_u_u字段;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
专用只读j_u_uTPAR i_u_u字段;
//方法
[调试程序隐藏]
公共f_u匿名类型0(j_uTPAR x,j_uTPAR y)
{
此.i__字段=x;
此.i__字段=y;
}
[调试程序隐藏]
公共覆盖布尔等于(对象值)
{
var type=作为f_uu匿名类型0的值;
返回((type!=null)和&EqualityComparer.Default.Equals(this.i__字段,type.i_字段))&&EqualityComparer.Default.Equals(this.i_字段,type.i_字段));
}
[调试程序隐藏]
公共覆盖int GetHashCode()
{
int num=-576933007;
num=(-1521134295*num)+EqualityComparer.Default.GetHashCode(此.i_u_字段);
返回(-1521134295*num)+EqualityComparer.Default.GetHashCode(这个.i__字段));
}
[调试程序隐藏]
公共重写字符串ToString()
{
StringBuilder=新的StringBuilder();
Append(“{x=”);
builder.Append(这个.i\u字段);
builder.Append(“,y=”);
builder.Append(这个.i\u字段);
builder.Append(“}”);
返回builder.ToString();
}
//性质
公共j_u_utpar x
{
得到
{
返回此.i__字段;
}
}
公共交通
{
得到
{
返回此.i__字段;
}
}
}

您可以投票支持此问题:

[编辑]来自Microsoft的响应:

我们已经研究了SecurityCritical迭代器,并决定不尝试使用它 至少在这个版本中,这是一个非常重要和重要的问题 复杂的工作,它似乎没有太大的用处,因为呼吁 通过IEnumerator.MoveNext将通过非关键 接口

我们可能会在以后的版本中再次讨论这个问题;特别是如果我们 请参阅它的常见场景


可能是
[SecurityCritical]
试图告诉你不要使用
var
并且更具体地说是类型?@BeemerGuy我不知道这会有什么改变,因为
var
是语法上的糖分,编译器只是用适当的类型来代替。这是Silverlight的吗?那么没关系,你反正没有签名的密钥。@Hans:不,这是针对WPF的。程序集已签名,代码访问安全性在所有其他方面都运行良好。当您说“调用”时,您是说涉及到反射吗?(我无法使用包含您指定的详细信息的尽可能简单的控制台应用程序来重新解决问题)
IEnumerable<MyItem> GetItems()
{
    foreach (var item in Items)
    {
        yield return item;
    }
}
   [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;
        }
    }
}