Andres
Andres

Reputation: 3414

How to access a member of a list inside a delegate

Well I think the title of this question is far to be clear but I hope the text below can clarity it.

The code below is a concept only but illustrates what I'm trying to do. How can I access a member of a List (inside the delegate) returned by a method without assigning it to a local List variable? Is that possible?

    static void ListTest()
    {
        int count = 0;

        List<int> even = Load().FindAll(delegate(int x)
        {
            count = Count; //<------- How can I get the Count from the List returned by the Load method?
            return (x % 2) == 0;
        });

        System.Console.WriteLine("Count = {0} and there are {1} even numbers", count, even.Count);
    }

    static List<int> Load()
    {
        List<int> array = new List<int>();
        int[] vet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        array.AddRange(vet);

        return array;
    }

Here's the original code - just to illustrate why I didn't want to create a new List, because it will only be a temporary list without any other use.

private List<MailItem> Find<T_Item, T_Adaptor>(T_Adaptor adaptor, MailItemId MailId)
{
    List<T_Item> Items = ((List<T_Item>)(typeof(T_Adaptor).InvokeMember(
            "Load",
            BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
            null, adaptor,
            new Object[] { null, MailId, null }))).FindAll(
                delegate(T_Item itm)
                {
                    MailItem mi = itm as MailItem;
                    if (mi == null) return false;
                    return (mi.StateInd.Code == StateInd.ASSIGNED); 
                });

    List<MailItem> mailItems = new List<MailItem>();
    foreach (T_Item itm in Items)
        mailItems.Add(itm as MailItem);

    return mailItems;
}

Thanks

Upvotes: 0

Views: 546

Answers (3)

Vlad
Vlad

Reputation: 35594

var load = Load();
List<int> even = load.FindAll(delegate(int x)
{
    count = load.Count;
    return (x % 2) == 0;
});

Edit:
One more idea about how to achieve the result you want using extension methods as syntactical sugar:

static public class ListExt
{
    static public List<T> StoreSize<T>(this List<T> self, out int size)
    {
        size = (self != null) ? self.Count : -1;
        return self;
    }
}
...
List<int> even = Load().StoreSize(out count).FindAll(x => (x % 2) == 0);

Upvotes: 2

VladV
VladV

Reputation: 10349

List<int> nums = Load();
List<int> even = nums.FindAll(delegate(int x)
        {
            count = nums.Count;
            return (x % 2) == 0;
        });

Otherwise, the object you need is not in the scope of the delagate.

Upvotes: 0

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391396

Unfortunately the list reference isn't available to your code since it only lives on the stack as part of temporary expression results used during the call chain.

As such, your only option is to explicitly store it away into a variable before using it.

In this example, I would do this:

var list = Load();
List<int> even = list.FindAll(delegate(int x)
{
    count = list.Count;
    return (x % 2) == 0;
});

Of course, now you can simply do:

var list = Load();
int count = list.Count;
List<int> even = list.FindAll(delegate(int x)
{
    return (x % 2) == 0;
});

And also rewrite to a lambda:

var list = Load();
int count = list.Count;
List<int> even = list.FindAll(x => (x % 2) == 0);

Upvotes: 1

Related Questions