C#.NET: loop through a collection to filter out items

I have a collection called CurrentAddressCollection which I need to loop through to filter out certain items, and then return that same collection. However, this filter should only apply when a certain condition is true, otherwise just return the collection as is.

I thought about using LINQ, like my example below, but it didn't work because LINQ returns an IEnumerable<Address> collection which is not the same type as the CurrentAddressCollection. And when I try to cast the IEnumerable collection as DomainList it returns null.

Question:
After using linq to filter out a collection, how do I get my collection to be of the same type before linq was applied?


...
gridAddresses.DataSource = GetDataSource().ToArray();
...

private DomainList GetDataSource()
{
	if (CurrentAddressCollection.ListOwner is CustomerQuote)
	{
		var addresses = CurrentAddressCollection.Cast<Address>().Where(a => a.AddressName != "ABC");
		return addresses as DomainList;
	}

	return CurrentAddressCollection;
}

public AddressHack CurrentAddressCollection
{
	get{return _currentAddressCollection;}
	set{_currentAddressCollection = value;}
}

Open in new window


More Info:
AddressHack is an abstract class that inherits from DomainList.

DomainList is an abstract class that has the ToArray() method:
public virtual DomainObject[] ToArray()
{
	return (DomainObject[]) List.ToArray(typeof(DomainObject));
}

Open in new window

LVL 8
pzozulkaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

chuang4630Commented:
Have you thought about the AutoMapper?
AndyAinscowFreelance programmer / ConsultantCommented:
A List has a RemoveAll method (details plus example):
https://msdn.microsoft.com/en-us/library/wdka673a%28v=vs.110%29.aspx

So just implement that to remove the items that match what you want from your list when you want to remove them.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
käµfm³d 👽Commented:
You won't be able to return an instance of your custom object without writing code to construct such an instance. If you were simply using a List or an array, then you could invoke the ToList or ToArray methods, respectively. It probably wouldn't be too much trouble to write an extension method to handle the creation of your custom object.

e.g.

public static class ExtensionMethods
{
    public static CurrentAddressCollection ToCurrentAddressCollection(this IEnumerable<Address> source)
    {
        // However you would normally populate a CurrentAddressCollection instance
    }
}

Open in new window

OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

AndyAinscowFreelance programmer / ConsultantCommented:
@kaufmed
and then return that same collection

Am I missing something?
käµfm³d 👽Commented:
I dunno...  I had a little trouble following the code supplied, but I thought "same collection" meant the same type of CurrentAddressCollection. Regardless of the type, if it's not List or array, then custom code is needed.

And if he indeed means to filter the existing collection, then removing the items as you suggest is feasible.
Easwaran ParamasivamCommented:
First in place, what is the connection between AddressHack  and Address? The CurrentAddressCollection is of type AddressHack. But you cast it to Address.

Assuming that all elements of CurrentAddressCollection are compatible with DomainList. If so, try..
var addresses = CurrentAddressCollection.Cast<DomainList>().Where(a => a.AddressName != "ABC");

Open in new window


If only few elements are compatible with DomainList then try below...

var addresses = CurrentAddressCollection.OfType<DomainList>().Where(a => a.AddressName != "ABC");

Open in new window


Otherwise try below...

var addresses = CurrentAddressCollection.OfType<Address>().Where(a => a.AddressName != "ABC");
return addresses as DomainList;

Open in new window


HTH.
pzozulkaAuthor Commented:
käµfm³d: Your understanding was correct in that after applying the linq code, I was hoping to get the same TYPE of collection back, instead of an IEnumerable.

Easwaran Paramasivam: The relationship is as follows:

public AddressHack CurrentAddressCollection { get; set; }

public abstract class AddressHack : DomainList, IAddressHack
{
   ...
}

public class AddressCollection<T> : AddressHack where T : Address, new()
{
   ...
}

Here's the code I tried to debug:
// ToArray() is a virtual method in the DomainList class. 
// CurrentAddressCollection is a "AddressHack", and "AddressHack" is a "DomainList"
grdAddresses.DataSource = GetDataSource().ToArray(); 
grdAddresses.DataBind();

private DomainList GetDataSource()
{
	if (condition == true)
	{
		var a = CurrentAddressCollection.OfType<Address>().Where(a => a.AddressName != "ABC");
		var b = a as DomainList;
		return b;
	}

	return CurrentAddressCollection;
}

Open in new window

After executing the linq code, a contains an IEnumerable collection of type <Address>. After executing the following line, b is null.
AndyAinscowFreelance programmer / ConsultantCommented:
>>then return that same collection.
In future please ask for what you want.  You are now asking for a different (new) collection to be returned.

Just what is the collection?  If it is a List then you could make a clone then use RemoveAll as I suggested previously.
For clone:
http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c

eg.
var newList = oldList.ToList();
pzozulkaAuthor Commented:
Andy, as of now, it seems that your solution seems to be the only one that would work, but at this point, I'm just trying to learn to see if the original collection type (less filtered out items) can be returned using the linq code above.

I use linq often, particularly in this context, to filter collections. From what I've gathered here, this is not possible without custom code.
AndyAinscowFreelance programmer / ConsultantCommented:
I try not to use linq if I can do it easily by traditional ways.  (I can usually rapidly scan and see errors in code but as soon as I come to linq or delegates I have to stop and think hard just what it is doing and what it is meant to do - not necessarily the same).

Use tools appropriate to the job.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.