我正在寻找创建匿名类型集合的最佳实践。
有几种方法 - this一种,this线程上的大多数答案都假定整个匿名集合可以在一个语句中构建。
由于匿名类型通常用于替换用于存储临时的类(如this SO answer中所提出的),我想避免为匿名集合创建和使用类,如{{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()对它们进行排序 - 很难看,但它有效......并且比现有代码更好。
答案 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;