1

所以我一直生活在迭代数据并以老式方式找到我感兴趣的东西的黑暗时代,但这个项目我认为我应该让事情变得更优雅并在我知道可以使用的地方使用 LINQ,但是事情不是很顺利。

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

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

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

因此,在我的代码中,我选择了 foo,并且我想创建一个包含所有具有匹配 barID 的 bar 的集合...

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 基础知识。

4

3 回答 3

6

您只需使用ObservableCollection 构造函数

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);
于 2012-05-16T20:12:18.010 回答
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>.

此结果实例不是数组,也不是 a List<T>,也不是ObservableCollection<T>. 演员表不能工作,因为ObservableCollection<T>不继承自WhereEnumerableIterator<T>. 如果你想ObservableCollection<T>从中得到一个,你需要转换。

在语法后面,该查询调用Enumerable.Where( msdn ),它返回一个IEnumerable<T>. 从该类型转换为所需类型的最简单方法是使用构造函数for ObservableCollection<T>

于 2012-05-16T20:56:13.463 回答
-4

您可以简单地使用“var”作为您的条形类型:

var bars = from data in fooCollection
where data.barID == fooCollection.SelectedItem.ID
select data;
于 2012-05-16T20:13:08.990 回答