如何使用LINQ查询泛型集合

时间:2012-01-05 11:17:06

标签: c# generics

我想知道LINQ通用集合的方法。

我的客户类是

 class Customer
    {
        public string Name { get; set; }
        public string id { get; set; }
    }

我的收藏类是

class genericCollection<T> : CollectionBase
{
    public void add(T GenericObject)
    {
        this.List.Add(GenericObject);
    }
}

然后我将一些数据添加到客户集合

  genericCollection<Customer> customers = new genericCollection<Customer>();
  customers.add(new Customer {id= "1",Name="Andy"});

  customers.add(new Customer { id = "2", Name = "MArk" });
  customers.add(new Customer { id = "3", Name = "Jason" });
  customers.add(new Customer { id = "4", Name = "Alex" });

现在我可以使用foreach循环遍历客户对象,但我怎样才能使用它。

我想使用像

这样的东西
var query =  from c in customers
             select c;

但我无法成功投出它。

此致 萨布

8 个答案:

答案 0 :(得分:5)

尝试将您的查询更改为以下内容(假设您的CollectionBase实施IEnumerable):

var query = from c in customers.OfType<Customer>() select c;

或让您的genericCollection<T>实施IEnumerable<T>

答案 1 :(得分:3)

有些答案建议使用customers.OfType<Customer>;这会在转换之前测试集合中每个对象的类型。您知道每个对象都属于该类型,因此您不需要运行时类型检查。因此,您应该使用customers.Cast<Customer>代替。

话虽如此,我同意最好不要首先使用CollectionBase;最好使用通用集合类型;如果您更喜欢定义自己的集合类型,那么您应该从(或委托)泛型集合派生。

答案 2 :(得分:2)

LINQ标准查询运算符是为IEnumerableIEnumerable<T>定义的扩展方法。你可以尝试:

class genericCollection<T> : Collection<T>

或使用其他集合类型,例如List<T>

答案 3 :(得分:1)

您需要实现IEnumerable<T>界面:

public class genericCollection<T>: CollectionBase, IEnumerable<T>{}

答案 4 :(得分:1)

您可以在LINQ查询中指定类型:

var query = from Customer c in customers select c;

或实施IEnumerable<T>例如:

class genericCollection<T> : CollectionBase, IEnumerable<T>
{
    public void add(T GenericObject)
    {
        this.List.Add(GenericObject);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return this.List.Cast<T>().GetEnumerator();
    }
}

答案 5 :(得分:0)

使用选择

customers.Select(x => {...})

答案 6 :(得分:0)

使用:

    public void add(T GenericObject)
    {
        this.List.Add(GenericObject);
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return this.List.OfType<T>().GetEnumerator();
    }

答案 7 :(得分:0)

现在,有一个库可以在打字稿中提供强类型的可查询集合。

这些集合是:

  • 列表
  • 字典

该库称为 ts-generic-collections-linq

GitHub上的源代码:

https://github.com/VeritasSoftware/ts-generic-collections

NPM:

https://www.npmjs.com/package/ts-generic-collections-linq

使用此库,您可以创建集合(如List<T>)并按如下所示查询它们。

    let owners = new List<Owner>();

    let owner = new Owner();
    owner.id = 1;
    owner.name = "John Doe";
    owners.add(owner);

    owner = new Owner();
    owner.id = 2;
    owner.name = "Jane Doe";
    owners.add(owner);    

    let pets = new List<Pet>();

    let pet = new Pet();
    pet.ownerId = 2;
    pet.name = "Sam";
    pet.sex = Sex.M;

    pets.add(pet);

    pet = new Pet();
    pet.ownerId = 1;
    pet.name = "Jenny";
    pet.sex = Sex.F;

    pets.add(pet);

    //query to get owners by the sex/gender of their pets
    let ownersByPetSex = owners.join(pets, owner => owner.id, pet => pet.ownerId, (x, y) => new OwnerPet(x,y))
                               .groupBy(x => [x.pet.sex])
                               .select(x =>  new OwnersByPetSex(x.groups[0], x.list.select(x => x.owner)));

    expect(ownersByPetSex.toArray().length === 2).toBeTruthy();

    expect(ownersByPetSex.toArray()[0].sex == Sex.F).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.length === 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.toArray()[0].name == "John Doe").toBeTruthy();

    expect(ownersByPetSex.toArray()[1].sex == Sex.M).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.length == 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.toArray()[0].name == "Jane Doe").toBeTruthy();