匿名类型集合?

时间:2009-03-19 10:20:27

标签: .net collections anonymous-types

我正在寻找创建匿名类型集合的最佳实践。

有几种方法 - this一种,this线程上的大多数答案都假定整个匿名集合可以在一个语句中构建。

由于匿名类型通常用于替换用于存储临时的类(如this SO answer中所提出的),我想避免为匿名集合创建和使用类,如{{3建议。

在我的情况下,我正在迭代一个集合 - 对于集合中的每个项目,我想以匿名类型(充当元组)收集相关对象。我需要将这些匿名类型放入集合中,然后对它们进行排序以进行进一步的工作。

我考虑的其他方法:

  1. 使用object []或ArrayList(失去匿名类型的好处)
  2. 为所需项目创建包装类(不再需要匿名类型)
  3. 这是我的代码中唯一需要这样一个集合的地方 - 最好的方法是什么?

    其他信息:

    我正在处理遗留的.Net 1.1对象,因此我使用的集合是实现IEnumerable的强类型集合,因此大多数Linq扩展方法(如.Select)都不起作用:

    代码示例

    foreach (Item item in myItems)
    {
        foreach (Confirmation confirmation in item.GetConfirmations(true))
        {
            if (lastParentId != item.ParentId)
            {
                lastParentId = item.ParentId;
                parentObject = new ParentItem(lastParentId);
            }
    
            itemHolder = new ArrayList { item, confirmation };
            if (parentObject!= null)
            {
                itemHolder.Add(parentObject.Rate);
            }
    
            sortConfirmations.Add(confirmation.Date, itemHolder);
        }
    }
    
    // Use sortConfirmations
    

    解决

    我最终使用通用字典一起收集相关项目并使用.OrderBy()对它们进行排序 - 很难看,但它有效......并且比现有代码更好。

7 个答案:

答案 0 :(得分:23)

如果您对数组感到满意,可以使用数组初始值设定项:

var items = new[] {
    new { Foo = "def" },
    new { Foo = "ghi" },
    new { Foo = "jkl" }
};

如果您想获得ToList(),则可以致电List<T>。由于不需要额外的复制,Marc的解决方案比调用ToList()稍微有效一点,但我认为在大多数情况下我可能会使用“数组然后ToList()”解决方案因为杂乱少了。当然,如果性能对于那段代码至关重要,它就会改变一切。

编辑:当你在一个集合上进行迭代时,只需使用Select

var anonymousItems = items.Select (item => new { Foo=item.Foo, 
                                                 Bar=item.Other })
                          .ToList();

答案 1 :(得分:6)

对于一个非常不同的答案...... LINQ?

  

在我的情况下,我正在迭代   集合 - 对于每个项目   收集我想收集   匿名类型中的相关对象   (充当元组)。我需要这些   要放入的匿名类型   收集然后对它们进行排序   进一步的工作。

听起来像是:

var list = (from item in collection
          from related in item.Relationship
          order by ...something...
          select new {item,related}).ToList()

答案 2 :(得分:4)

一种选择是使用示例项通过泛型类型推断创建集合,例如:

    static List<T> CreateEmptyList<T>(T template) {
        return new List<T>();
    }
    void Foo() {
        var list = CreateEmptyList(new { Foo = "abc" });
        list.Add(new { Foo = "def" });
        //...
    }

你也可以这样做而不用创建一个实例(但是使用永远不会得到调用者的匿名方法),但我认为它不会真正保存任何东西......我们可能不会创建一个实例对象,但我们确实创建了一个委托的实例,所以没有太多的保存......

您还提到了对数据进行排序;请参阅reply here以了解如何将List<T>.Sort与lambda一起使用,因此使用匿名类型 - 即。

list.Sort(x=>x.Foo);

答案 3 :(得分:1)

LINQ是要走的路。假设您想要获取集合项中每个项目的相关对象A,B和C,并按相关对象A排序,您将按如下方式进行。

var relatedObjects = items.
       Select(item => new { A = item.A, B = item.B, C = item.C } ).
       OrderBy(item => item.A);

您将获得一个匿名类型的项集合,其中三个属性A,B和C设置为相关对象A排序的相关对象。

我没有验证,但你应该能够在以后扩展relatedObject集合。只需执行以下操作即可添加一个新项目。这应该有效,因为每个程序集只有一个匿名类型,我认为如果每个属性的名称和类型匹配。

relatedObjects = relatedObjects.Union(
   Enumerable.Repeat(new { A = someA, B = someB, C = someC }, 1))

因为Enumerable.Repeat()而非常丑陋,但如果你与一组新项目而不是一个新项目结合,那就变得相当好了。

答案 4 :(得分:1)

我在寻找创建临时对象临时列表的方法时偶然发现了这个问题。 我为什么要创造这样的东西?我正在寻找一种快速方法来返回JSON,以获取由另一个对象的某些值组成的对象列表。这就是我的意思。

假设我在服务器端有一个Employee类,它在C#中如下所示:

public class Employee
{
          public int Id;
       public int businessGroupId;
       public string title;
       public int positionId;

       public string firstName;
       public string lastName;
       ...
}

此外,我有一些我可以轻松迭代的对象集合,如下所示:

List<Employee> allEmployees  = new List<Employee>();

现在,我想回到我的调用网页整个Employees 集合,但我只想要firstName,lastName为每个。我想让它们作为JSON返回。

这里的重点

我不想返回Employee对象中的每个属性。

我知道我可以通过迭代allEmployees集合并每次构建一个新对象来轻松创建一个匿名类型。

它看起来像下面这样:

foreach (Employee e in allEmployees)
{
    var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
}

什么是匿名类型? :)

现在的诀窍是我需要这些匿名对象的整个集合(List&lt;&gt;)。 但是,我无法为List提供我将使用的类型。我无法创造一个  List<unknown> allTempObjects = new List<unknown>();

或者我可以吗?

动态,可能

我可以执行以下操作并且效果很好:

List<dynamic> allEmployees  = new List<dynamic>();

foreach (Employee e in allEmployees)
{
           var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
        allEmployees.Add(tempObj);
}

// use the JavaScript Serializer to serialize the dynamic collection
JavaScriptSerializer jss = new JavaScriptSerializer();
// write the result out to the HTTP Stream (HtmlTextWriter in overridden Render method)

 writer.Write(jss.Serialize(allEmployees));

您将在客户端看到如下所示的JSON:

[
    {
      F_Name: "Seth",
      L_Name: "Godin"
    },
    {
       F_Name: "Charles",
       L_Name: "Petzold"
    },
    {
       F_Name: "Jeff",
       L_Name: "Prosise"
    }
]

最后,您可能会问我为什么要这样做。简单的答案是我想要新类型,它只用于序列化发送给我的客户端。匿名类型和匿名类型的匿名收集的一个很好的理由,你认为不是吗?

答案 5 :(得分:0)

  

这一个和大多数答案就此而言   线程假设整个匿名   集合可以构建在一个   言。

是的,您通常在单个语句中创建匿名类型的集合。如果你需要更多的陈述,你可能会得到一个非常无用的不同匿名类型的集合。

当您在单个语句中创建匿名类型时,它们非常有用,并且可以立即使用它们。如果集合的创建或进一步处理有点复杂,那么匿名类型会丢失它的一些用处。例如,您无法有效地将匿名类型传递给处理方法,因为该方法不知道对象的类型,因此必须使用反射来从中获取任何内容。

如果您要反复查找此匿名类型集合中的项目,您可能需要创建一个命名类型,以便将它们放入字典中以便更快地查找。

答案 6 :(得分:-1)

您可以这样创建收藏集

私有IList <((字符串名称,bool listenToQueue)> _listeners;