1

在下面的代码中,我想返回一个 IEnumerable 而不创建新的数据结构对象。但是,我收到以下代码的编译器错误。我错过了什么?

Error       Cannot implicitly convert type 'System.Reflection.FieldInfo[]' to 'System.Reflection.FieldInfo' 

public static IEnumerable<FieldInfo> GetAllFields(Type objectType)
{
   while (objectType != null)
   {
      //GetFields(...) returns a FieldInfo []
      yield return objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
      objectType = objectType.BaseType;
   }
}
4

6 回答 6

4

yield return对单个元素进行操作;你可以简单地返回返回值GetFields来实现你想要的。

为了进一步解释,yield return当您想在将其提供给调用者之前对序列中的每个项目应用一些操作时,它主要有用,但您不想预先完成所有这些工作并简单地返回聚合结果一个数组或List<T>.

yield return使这种延迟执行易于编写,因为生成的迭代器块仅在请求时将任何此类操作应用于每个项目。

编辑:对不起 - 我错过了你的代码的一个要点(枚举基本字段),但我会留下这个答案,因为我认为它可能还是有用的。Lasse Karlsen 的答案将满足您的需求,但除非您拥有庞大的类型层次结构,否则您并没有真正获得任何优势,而不仅仅是聚合结果并将它们返回到数组中。

于 2011-02-28T20:10:02.117 回答
4

Type.GetFields 返回一个 FieldInfo 对象的数组。

由于您没有返回数组集合,因此您必须遍历数组并返回其中的每个对象,有点像这样:

foreach (var fi in objectType.GetFields(...))
    yield return fi;
于 2011-02-28T20:11:19.243 回答
1

您可以尝试递归 + Concat

public static IEnumerable<FieldInfo> GetAllFields(Type objectType)
{
   if (objectType == null)
      return Enumerable<FieldInfo>.Empty;
   else 
      return objectType.GetFields(
                 BindingFlags.NonPublic | BindingFlags.Public |
                 BindingFlags.Instance | BindingFlags.DeclaredOnly)
         .Concat(GetAllFields(objectType.BaseType));
}
于 2011-02-28T20:18:40.490 回答
0

您正在寻找的是“整体收益”。您必须遍历并返回从 GetFields 返回的每个项目,然后将其设置为基类。

但这应该不是必需的,因为有一个标志可以指示是否包含基类定义。

于 2011-02-28T20:12:26.377 回答
0

稍微递归一下怎么样?

public static IEnumerable<FieldInfo> GetAllFields(Type objectType)
{      
      //GetFields(...) returns a FieldInfo []
      var fields = objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
      if(objectType.BaseType==null) return fields;
      return fields.Concat(GetAllFields(object.BaseType));
 }
于 2011-02-28T20:24:51.047 回答
0

正如大家所指出的,问题在于产生的元素类型与预期的类型不匹配。

为了避免每次都编写 for/while/foreach,我喜欢使用一种扩展方法来为我处理迭代。

public static class Sequence
{
    public static IEnumerable<T> Create<T>(T seed, Func<T, bool> predicate, Func<T, T> next)
    {
        for (T t = seed; predicate(t); t = next(t))
            yield return t;
    }
}

这样,您可以返回编写更具可读性的查询的字段

public static IEnumerable<FieldInfo> GetAllFields(Type objectType)
{
    BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
    return from type in Sequence.Create(objectType, t => t != null, t => t.BaseType)
        from field in type.GetFields(flags)
        select field;
}
于 2011-02-28T20:59:27.850 回答