重用/存储从委托创建的IEnumerable <t> </t>

时间:2014-11-21 14:43:17

标签: c# delegates ienumerable yield-return

我遇到了一个匿名委托的问题,我用它来构建集合的子集。

当时我坚持使用.Net Framework 2.0,所以不使用LINQ而是必须创建一些辅助函数来创建这些子集。

大多数情况下它工作正常,但似乎我不理解该委托的闭包,因为当它在范围之外进行评估时失败。

幸运的是,我设法在下面创建了一个显示问题的简单示例。

我已经实现了两个版本的迭代器。基本上总是工作的那个,不使用委托。并且使用它的人只能在内在的范围内工作。

我只是想知道为什么我不能依赖使用委托的实现,因为我打算将结果存储在变量中,并且我希望确保内容不会因为范围问题而改变。

更新:根据建议,将示例更改为控制台应用以使其更实用。删除了调试代码并缩短了列表长度。

下面是示例代码:

using System;
using System.Collections.Generic;
using System.Text;

namespace YuDoThisStap
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> variables = new List<string>();

            variables.Add("ab 12");
            variables.Add("cd 23");
            variables.Add("ef 34");
            variables.Add("gh 45");
            variables.Add("ij 67");
            variables.Add("kl 78");
            variables.Add("mn 89");
            variables.Add("op 90");

            List<int> numbers = new List<int>();
            for (int n = 0; n < 10; n++)
                numbers.Add(n);

            List<char> characters = new List<char>();
            for (char c = 'a'; c < 'p'; c++)
                characters.Add(c);

            Dictionary<string, IEnumerable<string>> results = new Dictionary<string, IEnumerable<string>>();
            foreach (int n in numbers)
            {
                foreach (char c in characters)
                {
                    IEnumerable<string> result = Select<string>(variables, delegate(string s) { return s.Contains(c.ToString()) && s.Contains(n.ToString()); });
                    //IEnumerable<string> result = ByNumber(ByCharacter(variables, c), n);

                    int count = 0;
                    foreach (string str in result)
                        count++;

                    if (count > 0)
                    {
                        string desc = "";
                        foreach (string v in result)
                            desc += v;
                        results.Add(string.Format("Condition (char = '{0}'; number = {1}, original = '{2}'):", c, n, desc), result);
                    }
                }
            }

            // Report results
            foreach (KeyValuePair<string, IEnumerable<string>> item in results)
            {
                Console.WriteLine(item.Key);
                foreach (string v in item.Value)
                    Console.WriteLine("\t" + v);
            }
        }

        public delegate TResult Func<TArg0, TResult>(TArg0 arg0);

        public static IEnumerable<string> ByCharacter(IEnumerable<string> source, char character)
        {
            foreach (string element in source)
                if (element.Contains(character.ToString()))
                    yield return element;
        }

        public static IEnumerable<string> ByNumber(IEnumerable<string> source, int number)
        {
            foreach (string element in source)
                if (element.Contains(number.ToString()))
                    yield return element;
        }

        public static IEnumerable<T> Select<T>(IEnumerable<T> source, Func<T, bool> predicate)
        {
            foreach (T element in source)
                if (predicate(element))
                    yield return element;
        }
    }
}

更新2 :我进一步简化了删除两个列表并看起来像是因为我正在使用在for / foreach中创建的变量。如果我创建一个时间变量,它可以工作,否则它比原始代码更差。

Dictionary<string, IEnumerable<string>> results = new Dictionary<string, IEnumerable<string>>();
for (int n = 0; n < 10; n++)
{
    for (char c = 'a'; c < 'p'; c++)
    {
        char c2 = c;
        int n2 = n;
        IEnumerable<string> result = Select<string>(variables, delegate(string s) 
        { 
            return s.Contains(c2.ToString()) && s.Contains(n2.ToString()); 
        });
        //IEnumerable<string> result = ByNumber(ByCharacter(variables, c), n);

        int count = 0;
        foreach (string str in result) count++;

        if (count > 0)
        {
            string desc = "";
            foreach (string v in result) desc += v;

            results.Add(string.Format("Condition (char = '{0}'; number = {1}, original = '{2}'):", c, n, desc), result);
        }
    }
}

0 个答案:

没有答案