Linq object Enumeration
I'm brand new to linq. I'm sure that I'm missing something due to inexperience.
the problem:
I am using linq to query objects and return enumerable Acct o开发者_如何转开发bjects where o.Diff!=0
if I try to enumerate the results I get the error unable to cast object of type System.Collections.Generic.KeyValuePair '2[Acct]' to type 'Acct'
.
the question: how can i return enumerable Acct objects from the Linq query?
Thanks in advance!
public class AcctSum
{
string ID;
Decimal Amt1;
Decimal Amt2;
Decimal Diff;
ArrayList<AcctDet> lines;
}
public class AcctInfo
{
Dictionary<string,AcctSum> acct
//code that adds the data...
public iEnumerable Discrepancies()
{
var results = (from Acct a in acct
where a.Diff != 0
select a).AsEnumerable<Acct>();
foreach (var result in results)//at runtime this generates an error
{
}
return results.GetEnumerator();
}
}
The problem is that as you iterate over your dictionary, you are casting each item as an Acct, when in fact, each of the items in your Dictionary is a KeyValuePair. Try something like:
from KeyValuePair<string,AcctSum> acctKVP in acct // assuming acct is of type Dictionary<string,AcctSum>
where acctKvp.Value.Diff != 0
When you iterate over acct
, each item is a key/value pair from the dictionary. Assuming the Acct
object is the value in each pair, you would get all of the nonzero accounts like this:
from a in acct.Values
where a.Diff != 0
select a
As others have said, it sounds like you want to be iterating over the values, not the key/value pairs.
That means you could use a query like this:
var results = from acctSum value in acct.Values
where acctSum.Diff != 0
select acctSum;
but personally I wouldn't bother using a query expression in this case. I'd just use the extension methods:
var results = acct.Values.Where(acctSum => acctSum.Diff != 0);
Now, in terms of the return type, I strongly suspect you want to return IEnumerable<AcctSum>
rather than IEnumerator
or IEnumerator<T>
. So you might want:
public IEnumerable<AcctSum> Discrepancies()
{
return acct.Values.Where(acctSum => acctSum.Diff != 0);
}
or you might want to "materialize" the query - get all the results in one go, and return those (rather than returning a query which can be iterated over lazily). For example:
public IEnumerable<AcctSum> Discrepancies()
{
return acct.Values.Where(acctSum => acctSum.Diff != 0).ToList();
}
In particular, by materializing the query you're allowing callers to modify acct
while they're iterating over these results - if they try to do so while they're iterating over the raw query, they'll get an exception.
You'll also need to change your AcctSum
class, because ArrayList
isn't a generic type in .NET. Did you mean to use List<T>
?
Well, it's b/c acct is a dictionary (which is an IEnumerable<KeyValuePair>, iirc, under the hood. Change your source from acct to acct.Values
First, the return type should be IEnumerator, not IEnumerable. Secondly, acct contains a collection of key value pairs, so you have to run the query on the key value (in this case)
void Main()
{
var acctInfo = new AcctInfo();
acctInfo.Discrepancies();
}
public class AcctSum
{
string ID;
Decimal Amt1;
Decimal Amt2;
public Decimal Diff;
ArrayList lines;
}
public class AcctInfo
{
public IEnumerator Discrepancies()
{
var acct = new Dictionary<int, AcctSum>
{{1, new AcctSum() {Diff = 0.0M}}, {2, new AcctSum() {Diff = 1.0M}}};
var results = (from AcctSum a in acct.Values where a.Diff != 0 select a).AsEnumerable();
foreach (var result in results)//at runtime this generates an error
{
}
return results.GetEnumerator();
}
}
精彩评论