【问题标题】:Return Anonymous Type from a function从函数返回匿名类型
【发布时间】:2011-09-21 02:59:25
【问题描述】:

我可以在函数中使用匿名类型作为返回类型,然后将返回值填充到某种数组或集合中,同时还向新数组/集合添加附加字段吗?原谅我的伪代码...

private var GetRowGroups(string columnName)
{
var groupQuery = from table in _dataSetDataTable.AsEnumerable()
                             group table by new { column1 = table[columnName] }
                                 into groupedTable
                                 select new
                                 {
                                     groupName = groupedTable.Key.column1,
                                     rowSpan = groupedTable.Count()
                                 };
    return groupQuery;

}

private void CreateListofRowGroups()
{
    var RowGroupList = new List<????>();
    RowGroupList.Add(GetRowGroups("col1"));
    RowGroupList.Add(GetRowGroups("col2"));
    RowGroupList.Add(GetRowGroups("col3"));

}

【问题讨论】:

标签: c# linq generics collections


【解决方案1】:

这是very popular question。通常,由于需要强类型,您不能返回匿名类型。但是有几个解决方法。

  1. 创建一个简单的类型来表示返回值。 (见here 和here)。通过generating from usage 让它变得简单。
  2. 使用示例实例为cast to the anonymous type 创建一个辅助方法以进行强制转换。

【讨论】:

  • 请始终从外部链接中引用一些 sn-p。在这种情况下,第一个已损坏,因此您的答案毫无用处。
  • “从使用中生成”链接已损坏
  • @dlchambers:谢谢。我将链接更改为使用来自 Wayback 机器的存档。
  • @mellamokb,除了 OP 之外,其他人都将这个结果显示为他们最热门的谷歌点击之一,因此将每个未来的用户重定向回谷歌是完全没有帮助的。感谢您为回答所做的努力,但请在回答中插入重要信息,或者如果您只是重新指向其他资源,请发表评论。
【解决方案2】:

不,你不能从方法中返回匿名类型。有关更多信息,请阅读 this MSDN 文档。使用class 或struct 而不是anonymous 类型。

您应该阅读博文 - Horrible grotty hack: returning an anonymous type instance

如果您使用的是框架 4.0,那么您可以返回 List&lt;dynamic&gt;,但要小心访问匿名对象的属性。

private List<dynamic> GetRowGroups(string columnName)
{
var groupQuery = from table in _dataSetDataTable.AsEnumerable()
                             group table by new { column1 = table[columnName] }
                                 into groupedTable
                                 select new
                                 {
                                     groupName = groupedTable.Key.column1,
                                     rowSpan = groupedTable.Count()
                                 };
    return groupQuery.ToList<dynamic>();
}

【讨论】:

【解决方案3】:

不,您不能直接返回匿名类型,但您可以使用impromptu interface 返回它。像这样的:

public interface IMyInterface
{
    string GroupName { get;  }
    int RowSpan { get; }
}

private IEnumerable<IMyInterface> GetRowGroups()
{
    var list =
        from item in table
        select new
        {
            GroupName = groupedTable.Key.column1,
            RowSpan = groupedTable.Count()
        }
        .ActLike<IMyInterface>();

    return list;
}

【讨论】:

  • 可爱,但我不太确定这是否比将类型具体化更容易......(IDE 中的工具可以提供帮助)
【解决方案4】:

只需使用和ArrayList

    public static ArrayList GetMembersItems(string ProjectGuid)
    {
        ArrayList items = new ArrayList(); 

              items.AddRange(yourVariable 
                        .Where(p => p.yourproperty == something)
                        .ToList());
            return items;
    }

【讨论】:

    【解决方案5】:

    使用object,而不是var。但是,您必须使用反射来访问匿名类型范围之外的属性。

    即

    private object GetRowGroups(string columnName) 
    ...
    var RowGroupList = new List<object>();
    ...
    

    【讨论】:

    • 这可以稍后通过dynamic (C#4) 访问...但是它失去了所有实际的类型安全性。
    【解决方案6】:

    在 C#7 中,您可以返回元组列表:

    private IEnumerable<(string, string)> GetRowGroups(string columnName)
    {
        return from table in _dataSetDataTable.AsEnumerable()
               group table by new { column1 = table[columnName] }
               into groupedTable
               select (groupedTable.Key.column1, groupedTable.Count());
    }
    

    你甚至可以给元组的成员起名字:

    private IEnumerable<(string groupName, string rowSpan)> GetRowGroups(string columnName)
    {
        return from table in _dataSetDataTable.AsEnumerable()
               group table by new { column1 = table[columnName] }
               into groupedTable
               select (groupedTable.Key.column1, groupedTable.Count());
    }
    

    但是,您需要来自 Nuget 包管理器的System.ValueTuple。

    无论如何,我建议给事物起一个清晰的名称,包括它们的用途,尤其是当它是公共 API 的一部分时。话虽如此,您应该考虑创建一个包含这些属性的类并返回该类型的列表。

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 1970-01-01
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多