C#中的收益率返回 - 对字段的公开进行失败测试

时间:2014-11-06 22:46:20

标签: c# public ienumerator

今天我遇到了与C#相关的问题。我必须编写一个程序来通过一些测试。我实现的一切都正常工作,但有一个测试不允许使用公共字段,但它失败了。

我有一个实现IEnumerable的泛型类,导致问题的是:

public IEnumerator<R> GetEnumerator()
{
    foreach (R r in roomList)
        yield return r;
}

如果我把这个类“返回null”,测试通过正常。我想知道什么是错的?这是一份测试报告:

Result Message:       Assert.Fail failed. Detected type "Exercise.Hotel`2+<GetEnumerator>d__0" with public filed(s) "Exercise.Hotel`2[R,SC] <>4__this, R <r>5__1, Enumerator <>7__wrap2", which is not allowed.

这里也是测试代码。说实话,我不太熟悉它是如何工作的。当然也可能是由于测试不好造成的。

        var withPublicField = types.Where(t => !t.IsEnum)
            .Where(t => t.GetFields(BindingFlags.Public | BindingFlags.Instance).Count() > 0)
            .Where(t => !t.Name.StartsWith("<>c__DisplayClass"))
            .ToDictionary(t => t.FullName, t => t.GetFields(BindingFlags.Public | BindingFlags.Instance));

感谢您的帮助。这是我的第一个问题所以我希望我做得很好:)

2 个答案:

答案 0 :(得分:5)

这是你正在谈论的一个奇怪的考验。

迭代器方法(即其中包含yield return的方法)触发失败的原因是C#编译器重写此类方法以返回将该方法实现为状态机的隐藏类的实例。这种类型中包含不允许的公共字段。

就个人而言,我认为失败是误报。虽然我同意公共字段通常是令人厌恶的,但在这种情况下,您正在处理隐藏的,编译器生成的代码。这种特殊情况应该没问题。

希望你能在这种情况下抑制失败,并解释“这不是我的错!”另一种方法是实现自己的类,为场景实现IEnumerator<T>类型,当然不包含公共字段。

编辑:我注意到测试代码已经尝试排除编译器生成的捕获变量代码(即Name.StartsWith("<>c__DisplayClass"))。因此,测试作者可能会为编译器生成的<GetEnumerator>类型添加类似的排除(当然,根据Lee的答案检查[CompilerGenerated])。

答案 1 :(得分:4)

您可能希望忽略编译器生成的类,这些类应使用CompilerGeneratedAttribute

进行修饰
var withPublicField = types
    .Where(t => !t.IsEnum)
    .Where(t => Attribute.GetCustomAttribute(t,typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)) == null)
...