代码之家  ›  专栏  ›  技术社区  ›  Mike Ohlsen

c#lambda表达式-将委托结果添加到常规列表

  •  1
  • Mike Ohlsen  · 技术社区  · 15 年前

    我有一份代表的一般名单。每个委托函数返回一个枚举值,指示函数中发生了什么。在对委托求值时,如果枚举不是特定的枚举值,则需要将其添加到列表中。

    免责声明: 这里的代码非常通用,真正的代码实际上在委托中做一些事情来确定返回值!


    class Class1
    {
        public enum WhatHappened
        {
            ThingA,
            ThingB,
            Nothing
        }
    
        private delegate WhatHappened del();
    
        public static List<WhatHappened> DoStuff()
        {
            List<del> CheckValues = new List<del>();
    
            List<WhatHappened> returnValue = new List<WhatHappened> { };
    
            CheckValues.Add(delegate { return method1(); });
            CheckValues.Add(delegate { return method2(); });
    
            CheckValues.ForEach(x =>
            {
                WhatHappened wh = x();
                if (wh != WhatHappened.Nothing)
                    returnValue.Add(wh);
            });
    
            return returnValue;
    
        }
    
        private static WhatHappened method1()
        {
            return WhatHappened.Nothing;
        }
    
        private static WhatHappened method2()
        {
            return WhatHappened.ThingA;
        }
    
    }
    

    注:

    CheckValues.ForEach(x => returnValue.Add(x()));
    
    7 回复  |  直到 12 年前
        1
  •  9
  •   Jon Skeet    15 年前

    好的,几点建议:

    • del . 在这种情况下,我会使用 Func<WhatHappened> -但是如果你
    • 而不是使用匿名方法添加到 CheckValues ,你只需使用:

      CheckValues.Add(method1);
      CheckValues.Add(method2);
      

    • 我建议不要使用Pascal case作为局部变量名的开头。

    • returnValues 真的没有为你做任何事-打电话给 List<T> 构造函数,或者使用我下面的代码,它不需要局部变量。
    • 如果你的名单 真正地 里面只有两名代表,我会分别给他们打电话。这要简单得多。
    • return CheckValues.Select(x => x())
                        .Where(wh => wh != WhatHappened.Nothing)
                        .ToList();
      

    public static List<WhatHappened> DoStuff()
    {
        var functions = new List<Func<WhatHappened>> { Method1, Method2 };
    
        return functions.Select(function => function())
                        .Where(result => result != WhatHappened.Nothing)
                        .ToList();
    }
    

    method1 method2 已重命名以符合命名约定。当然,在现实生活中,我相信他们会有更多有用的名字……)

        2
  •  3
  •   Denis Troller    15 年前

    public static List<WhatHappened> DoStuff()
    {
        List<del> CheckValues = new List<del>();
    
        List<WhatHappened> returnValue = new List<WhatHappened>();
    
        CheckValues.Add(method1);
        CheckValues.Add(method2);
    
        return CheckValues
                   .Select(dlg => dlg())
                   .Where( res => res != WhatHappened.Nothing)
                   .ToList();
    }
    

    请注意,如果需要,也可以使用Func而不是声明委托类型,但在这种情况下就不那么简洁了。 另外,我会退回一张支票 IEnumerable<WhatHappened> 而不是列表,但都是关于上下文的。

        3
  •  3
  •   chakrit Dutchie432    15 年前

    通过链接Select(map)和Where(filter)而不是多个FOR循环和IF语句,您可以一直使用lambda

    // get results from the list of functions
    var results = CheckValues.Select(x => x());
    
    // filter out only the relevant ones.
    var returnValues = results.Where(x => x != WhatHappened.Nothing);
    

    基本上,你应该多想想 declaratively imperatively

        4
  •  2
  •   JaredPar    15 年前

    编写以下内容而不是使用delegate关键字更为惯用。但它不会改变底层功能。

    CheckValues.Add( () => method1() );
    

    另外,我发现重写ForEach更具可读性,如下所示

    CheckValues = CheckValues.
      Select(x => x()).
      Where(wh => wh != WhatHappened.Nothing ). 
      ToList();
    
        5
  •  1
  •   Jose Basilio    15 年前

    在我看来,基于这个例子,它看起来不错。您可以通过替换以下内容进行更多重构:

    CheckValues.Add(delegate { return method1(); });
    CheckValues.Add(delegate { return method2(); });
    

    CheckValues.Add(() => WhatHappened.Nothing);
    CheckValues.Add(() => WhatHappened.ThingA);
    
        6
  •  1
  •   Michael Meadows    15 年前

    以下是一个无LINQ的解决方案:

    return CheckValues
        .ConvertAll<WhatHappened>(x => x())
        .FindAll(y => y != WhatHappened.Nothing);
    

    警告

        7
  •  0
  •   Gishu    15 年前


    更新: 从Jon n Jared的帖子中找到了一些可以列举的优点

    private delegate WhatHappened WhatHappenedDelegate();
    
    public static List<WhatHappened> DoStuff()
    {
        WhatHappenedDelegate delegateChain = null;
        delegateChain += method1;
        delegateChain += method2;
    
        return delegateChain.GetInvocationList() 
                .Select(x => (WhatHappened) x.DynamicInvoke())
                .Where( wh => (wh != WhatHappened.Nothing))
                .ToList<WhatHappened>();
    }