7

我有一个使用迭代器块返回的简单方法IEnumerable<T>

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

通常,此方法工作正常,但如果我将[SecurityCritical]属性应用到程序集(或包含上述方法的类),它会TypeLoadException在尝试调用该方法时抛出 a。无法加载的类型是编译器生成的与迭代器方法相对应的类,它GetEnumerator是导致问题的方法,因为它是安全透明的。

为了比较,如果我修改上述方法以填充并返回 a List<MyItem>,一切正常。

有什么建议么?

谢谢,

蒂姆。

4

3 回答 3

3

这不是最好的做法,所以希望你能找到更好的方法,但你总是可以放弃编译器生成的代码并创建自己的实现类IEnumerator<MyItem>(也许你自己的类实现IEnumerable<MyItem>- 取决于复杂性,这样做可能会使事情变得更容易或更困难),然后或多或少地像在 .NET2.0 之前的日子里那样构建枚举器。

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

IEnumerator当 99% 的时间对我们来说非常好时,必须构建一个类总是有点令人失望yield,但仍然有必要的时候,它可能会在这里解决你的问题。

于 2010-11-30T11:26:55.910 回答
3

在一个复杂的应用程序中,我遇到了同样的问题。Spring介于两者之间并说'blahblah'类型不是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;
        }
    }
}
于 2010-12-04T09:56:11.627 回答
0

您可以为此问题投票:https ://connect.microsoft.com/VisualStudio/feedback/details/667328/yield-and-securitycriticalattribute-problem

[编辑] 微软的回应:

我们已经查看了 SecurityCritical 迭代器,并决定至少在此版本中不尝试使其工作。这是一项重大而复杂的工作,而且似乎不太有用,因为通过 IEnumerator.MoveNext 的调用将通过非关键接口进行调用。

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

于 2011-05-10T09:34:29.813 回答