编写简单的LINQ查询

时间:2012-05-16 20:09:53

标签: c# wpf linq

所以我一直生活在黑暗的时代,迭代我的数据,找到我感兴趣的老式方式,但这个项目我认为我应该让事情更优雅,并使用LINQ,我知道它可以是用过,但事情并没有完全点击。

所以我有两个简单的ObservableCollections,我想从其中一个中提取所有数据,匹配另一个当前所选项目。对象非常简单......

public class foo
{
    //....
    public string barID{ get; set; }
    //....
}

public class bar
{
    public string ID { get; set; }
    //....
}

所以在我的代码中我有选择的foo,我想要创建一个具有匹配barID的所有条的集合...

ObservableCollection<bar> bars = 
    from data in fooCollection
    where data.barID == barCollection.SelectedItem.ID
    select data;

所以我根据我在网上找到的LINQ的语法尝试了这个,但这会抛出一个无法隐式地将IEnumerable强制转换为ObservableCollection的编译错误。所以我试过......

ObservableCollection<bar> bars = 
    (ObservableCollection<bar>)
    (from data in fooCollection
    where data.barID == barCollection.SelectedItem.ID
    select data);

编译但会抛出运行时错误...

Unable to cast object of type 
'WhereEnumerableIterator`1[TestProj.bar]' to type 
'System.Collections.ObjectModel.ObservableCollection`1[TestProj.bar]'.

所以我确信我可以在事后投射对象或做其他事情,但我一直在寻找尽可能优雅的解决方案,所以有点帮助将这个简单的LINQ语句放在一起将不胜感激。此外,对幕后发生的事情的简单解释将极大地帮助我理解一些LINQ基础知识。

3 个答案:

答案 0 :(得分:6)

您只需使用ObservableCollection constructor

IEnumerable<bar> barEnumerable = 
    from data in fooCollection
    where data.barID == barCollection.SelectedItem.ID
    select data;

ObservableCollection<bar> bars = new ObservableCollection<bar>(barEnumerable);

基本上是:

IEnumerable<bar> barEnumerable = 
fooCollection.Where(data => data.barID == barCollection.SelectedItem.ID);

答案 1 :(得分:2)

转换会更改表达式的类型,如果表达式确实是该类型,它将起作用。

考虑class Customer : Person

Customer c = new Customer();
Person p = c;  //no problem;  this is an implicit up-cast (from child to parent)
Customer c2 = p;  //compiler doesn't allow because
                  //p may refer to a Person instance that isn't a Customer
Customer c3 = (Customer) p; //we certify to the compiler that p is referencing
                            //a Customer instance, and we take responsibility
                            //for an exception if we are wrong.
                            // this is a down-cast (from parent to child)
Customer cSafe = p as Customer; //safe down-cast, we get a null in cSafe if we are wrong

由于可能存在例外情况,因此在我的代码中,向下转换极为罕见。让我们花一点时间来感谢Generics让这成为可能。好的,转换:

转换从旧实例创建所需类型的新实例。

Customer c4 = new Customer(p); //conversion constructor
Customer c5 = p.ToCustomer(); //conversion method
Customer c6 = (Customer) p; // if defined, implicit conversion. Otherwise, casting
                            // yes, casting and implicit conversion are the same syntax
                            // terribly confusing.

我们从异常消息中知道查询返回的实例是WhereEnumerableIterator<TestProj.bar>

此结果实例不是数组,不是List<T>,而不是ObservableCollection<T>。强制转换不起作用,因为ObservableCollection<T>不会从WhereEnumerableIterator<T>继承。如果您需要ObservableCollection<T>,则需要转换。

在语法后面,该查询调用Enumerable.Wheremsdn),返回IEnumerable<T>。从该类型转换为所需类型的最简单方法是使用ObservableCollection<T> {{1}}。

答案 2 :(得分:-4)

您只需使用“var”作为条形类型:

var bars = from data in fooCollection
where data.barID == fooCollection.SelectedItem.ID
select data;