C# lambda 表达式 - 将委托结果添加到通用列表

发布于 2024-07-18 02:13:04 字数 1367 浏览 3 评论 0原文

问题:我刚刚使用 C# lambda 表达式编写了第一个代码。 它有效,但我不确定这是否是最好的方法。 关于 lambda 表达式的更好方法有什么建议吗? 像我下面这样的表达式中有很多行代码似乎很奇怪。

背景:我有一份代表的通用名单。 每个委托函数都会返回一个枚举值,指示函数中发生的情况。 在评估委托时,如果枚举不是特定的枚举值,我需要将其添加到列表中。

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


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;
    }

}

注意:我最初使用 lambda 来添加所有项目(见下文),然后删除我不想要的项目(WhatHappened.Nothing)。

CheckValues.ForEach(x => returnValue.Add(x()));

Question: I have just wrote my first code using c# lambda expressions. It works, but I am not sure if this is the best way to do it. Any recommendations on a better way to do the lambda expression? It seems odd to have numerous lines of code in the expression like I do below.

Background: I have a generic list of delegates. Each delegate function returns an enum value indicating what happened in the function. Upon evaluation of the delegate, I need to add the enum to a List if it was not a specific enum value.

Disclaimer: Code here is very generic, the real code actually does stuff in the delegates to determine the return value!


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;
    }

}

Note: I originally had the lambda like adding all the items (see below), then removing the ones I didn't want (WhatHappened.Nothing).

CheckValues.ForEach(x => returnValue.Add(x()));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无需解释 2024-07-25 02:13:04

好的,有一些建议:

  • 不要调用您的委托 del。 在本例中,我将使用 Func - 但如果您确实想要声明自己的委托类型,请为其指定一个更具描述性的名称,并遵守 . NET 命名约定。
  • 您可以使用以下方法,而不是使用匿名方法添加到 CheckValues

    CheckValues.Add(方法1); 
      CheckValues.Add(方法2); 
      

    编译器会将方法组转换为委托。

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

  • returnValues 的集合初始值设定项实际上并没有为您做任何事情 - 只需像平常一样调用 List 构造函数,或者使用下面的我的代码,该代码不需要局部变量开始。
  • 如果您的列表中确实只有两名代表,我会分别致电他们。 简单多了。
  • 否则,您确实可以按照 Jared 的建议使用 LINQ,但我的做法略有不同:

    return CheckValues.Select(x => x()) 
                        .Where(wh => wh != WhatHappened.Nothing) 
                        .ToList(); 
      

编辑:按照建议,这是完整的示例。 不过,它与 Denis 的不太一样......我做了一些更改:)

public static List<WhatHappened> DoStuff()
{
    var functions = new List<Func<WhatHappened>> { Method1, Method2 };

    return functions.Select(function => function())
                    .Where(result => result != WhatHappened.Nothing)
                    .ToList();
}

(我假设 method1method2 已被重命名以适应命名约定。当然,在现实生活中我相信他们会有更有用的名字......)

Okay, a few suggestions:

  • Don't call your delegate del. In this case, I'd use Func<WhatHappened> - but if you do want to declare your own delegate type, give it a more descriptive name, and obey the .NET naming conventions.
  • Instead of using anonymous methods to add to CheckValues, you can just use:

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

    The compiler will convert the method groups into delegates.

  • I'd recommend not using Pascal case for a local variable name to start with.

  • Your collection initializer for returnValues isn't really doing anything for you - just call the List<T> constructor as normal, or use my code below which doesn't require a local variable to start with.
  • If your list really only has two delegates in it, I'd just call them separately. It's a lot simpler.
  • Otherwise you can indeed use LINQ as Jared suggests, but I'd do it slightly differently:

    return CheckValues.Select(x => x())
                      .Where(wh => wh != WhatHappened.Nothing)
                      .ToList();
    

EDIT: As suggested, here's the full example. It's not quite the same as Denis's though... I've made a couple of changes :)

public static List<WhatHappened> DoStuff()
{
    var functions = new List<Func<WhatHappened>> { Method1, Method2 };

    return functions.Select(function => function())
                    .Where(result => result != WhatHappened.Nothing)
                    .ToList();
}

(I'm assuming that method1 and method2 have been renamed to fit the naming convention. Of course in real life I'm sure they'd have more useful names anyway...)

夏尔 2024-07-25 02:13:04

我会简单地使用 Linq,但这只是我的想法:

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 而不是列表,但这完全取决于上下文。

I would simply use Linq, but that's just me:

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();
}

Note that you can also use Func instead of declaring a Delegate type if you want, but that's less terse in that case.
Also, I'd return an IEnumerable<WhatHappened> instead of a List, but it's all about the context.

离笑几人歌 2024-07-25 02:13:04

您可以通过链接 Select(映射)和Where(过滤器)而不是多个 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);

基本上,您应该考虑更多 声明式 而不是 当使用 lambda 时,必须如此。 它将帮助您编写更优雅的代码。

You can go lambda all the way by chaining Select (map) and Where (filter) instead of multiple FOR loops and IF statements

// 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);

Basically, you should think more declaratively instead of imperatively when work ing with lambdas. It'll help you write more elegant code.

無心 2024-07-25 02:13:04

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

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

另外,我发现将 ForEach 重写为以下内容更具可读性

CheckValues = CheckValues.
  Select(x => x()).
  Where(wh => wh != WhatHappened.Nothing ). 
  ToList();

It's a bit more idiomatic to write the following instead of using the delegate keyword. It doesn't change the underlying functionality though.

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

Also, I find it more readable to rewrite the ForEach as the following

CheckValues = CheckValues.
  Select(x => x()).
  Where(wh => wh != WhatHappened.Nothing ). 
  ToList();
蓝戈者 2024-07-25 02:13:04

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

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

CheckValues.Add(() => WhatHappened.Nothing);
CheckValues.Add(() => WhatHappened.ThingA);

In my opinion, based on the example, it looks fine. You could refactor even more by replacing:

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

with:

CheckValues.Add(() => WhatHappened.Nothing);
CheckValues.Add(() => WhatHappened.ThingA);
<逆流佳人身旁 2024-07-25 02:13:04

下面是一个不依赖 LINQ 的解决方案:

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

警告

这不是性能最佳的解决方案,因为它会迭代两次。

Here's a LINQ-free solution:

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

caveat

This is not the most performant solution, as it would iterate twice.

莫言歌 2024-07-25 02:13:04

我无法理解代码的目的..但是这里是。
使用委托链
更新:并从 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>();
}

I can't fathom the purpose of the code.. however here goes.
Used delegate chaining
Update: and picked up some Enumerable goodness from Jon n Jared's posts

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>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文