2

I have a function that returns an array of objects. The problem is, the objects can be one of three different types. I am trying to break these objects into arrays of the different custom types.

For example:

var collection = something.ReturnObjArray();
var Details = collection.Where(a => a is DetailItem);
var Addenda = collection.Where(a => a is AddendaItem);

If i do the above and try to access the data in a foreach loop to put the Addenda in a collection within the Detail Items:

foreach (var addendaItem in Addenda)
{
    var detailItem = Details.Single(d => d.DetailAddendaKey == addendaItem.Key);
    detailItem.Addenda.Add(addendaItem);
}

I get errors like :

'object' does not contain a definition for 'DetailAddendaKey' and no extension method 'DetailAddendaKey' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

Among others. If i try and change the var for Details and Addenda to:

IEnumerable<DetailItem> Details = collection.Where(a => a is DetailItem);
IEnumerable<AddendaItem> Addenda = collection.Where(a => a is AddendaItem);

I get past the error above, but now get:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<object>' to 'System.Collections.Generic.IEnumerable<MyNameSpace.DetailItem>'. An explicit conversion exists (are you missing a cast?)

Any ideas what I need to do?

2
  • what should be DetailAddendaKey? does this property belong to Detail class? Commented Dec 21, 2012 at 16:39
  • Yes. It's how i was linking them together. Commented Dec 21, 2012 at 17:49

2 Answers 2

7

Use OfType<T>.

Filters the elements of an IEnumerable based on a specified type.

Example:

IEnumerable<DetailItem> Details = collection.OfType<DetailItem>();
Sign up to request clarification or add additional context in comments.

Comments

1

I suspect that this sentence returns an object of type object[] (an object array):

var collection = something.ReturnObjArray();

object doesn't have the whole properties!

That's why Details.Single(d => d.DetailAddendaKey == addendaItem.Key) complains about that d doesn't have a property DetailAddendaKey.

You need to do this:

var Details = collection.Where(a => a is DetailItem).Cast<DetailItem>();
var Addenda = collection.Where(a => a is AddendaItem).Cast<AddendaItem>();

Or as @Mark Byers suggested (which is an abbreviation of above sample):

var Details = collection.OfType<DetailItem>();
var Addenda = collection.OfType<AddendaItem>();

This is downcasting all items in the IEnumerable<object> to DetailItem or AddendaItem, meaning that you'll have an IEnumerable<DetailItem> and IEnumerable<AddendaItem> after all!

Then, the next sentences will compile and work as you expect.

Note

OfType<T>() should be a better choice since your approach of using is operator and later calling Cast<T>() is downcasting twice each object in the object array.

Check this other question and its answers for more info about is operator and its behavior:

1 Comment

That did it. Mark's would have worked as well I'm sure. I don't know why i didn't think of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.