如何使用谓词在 C# 中创建扩展方法

发布于 2024-11-16 17:02:54 字数 687 浏览 3 评论 0原文

我正在尝试创建一个名为 RemoveWhere 的扩展方法,该方法根据谓词从 List 集合中删除项目。例如

var result = products.RemoveWhere(p => p.ID == 5);

我使用 Microsoft 的Where 扩展方法签名作为起点。到目前为止,这是我所得到的:

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, List<T>> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???

}

我不知道如何使用谓词。有人可以帮我完成这个吗?谢谢你!

I'm trying to create an extension method called RemoveWhere that removes an item from a List collection based on a predicate. For example

var result = products.RemoveWhere(p => p.ID == 5);

I'm using Microsoft's Where extension method signature as a starting point. Here's what I have so far:

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, List<T>> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???

}

I don't know how to use the predicate. Can someone help me finish this? Thank you!

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

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

发布评论

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

评论(4

长亭外,古道边 2024-11-23 17:02:54

Predicate 参数应该是: Func

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, bool > predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???
    var result = new List<T>();
    foreach(var item in source)
    {
        if(!predicate(item))
        {
            result.Add(item);
        }
    }

    return result;
}

EDIT: 正如其他人所指出的,此方法要么命名错误,要么已经存在于 List 中。我的猜测只是您试图了解方法本身如何使用传入的委托。为此,您可以查看我的示例。如果这不是您的意图,我将删除这个答案,因为代码确实毫无意义。

The Predicate parameter should be: Func<T,bool>

public static List<T> RemoveWhere<T>(this List<T> source, Func<T, bool > predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source", "The sequence is null and contains no elements.");
    }

    if (predicate == null)
    {
        throw new ArgumentNullException("predicate", "The predicate function is null and cannot be executed.");
    }

    // how to use predicate here???
    var result = new List<T>();
    foreach(var item in source)
    {
        if(!predicate(item))
        {
            result.Add(item);
        }
    }

    return result;
}

EDIT: As others have pointed out, this method is either misnamed, or it already exists on List. My guess is just that you're trying to understand how a passed in delegate is used by the method itself. For that you can look at my sample. If that is not your intent, I'll delete this answer as the code really is kind of pointless.

柠檬心 2024-11-23 17:02:54

列表中已经有一个方法可以尝试这样做。 Predicate 应该是 Predicate 那么你可以使用 source.RemoveAll(predicate)

There is already a method in list that does that try. Predicate should be a Predicate then you can use source.RemoveAll(predicate)

能怎样 2024-11-23 17:02:54

正如其他人指出的那样, List.RemoveAll 将执行您想要的操作。但是,如果这是一次学习体验,或者您想要对任何 IList(没有 RemoveAll)进行操作,则这应该与 执行相同的操作RemoveAll 而是作为扩展方法。

public static void RemoveWhere<T>(this IList<T> source, Func<T, bool> predicate)
{
  //exceptions here...

  // how to use predicate here???
  for(int c = source.Count-1 ; c >= 0 ; c--)
  {
    if(predicate(source[c]))
    {
      source.RemoveAt(c);
    }
  }
}

As others have pointed out, List<T>.RemoveAll will do what you want. If however, this is a learning experience or you want to operate on any IList<T> (which doesn't have RemoveAll) this should do the same as RemoveAll but as an extension method.

public static void RemoveWhere<T>(this IList<T> source, Func<T, bool> predicate)
{
  //exceptions here...

  // how to use predicate here???
  for(int c = source.Count-1 ; c >= 0 ; c--)
  {
    if(predicate(source[c]))
    {
      source.RemoveAt(c);
    }
  }
}
简单 2024-11-23 17:02:54

正如 boca 观察到的,List 已经有一个方法可以做到这一点。不过,一个更大的问题是,这确实不是您应该创建新扩展方法的场景。已经有一个采用谓词的扩展方法:Where

当然,这样做:

var result = list.Where(x => x != 5).ToList();

比使用 RemoveAll 代码多一点:

list.RemoveAll(x => x == 5);

但是:

  • 它还会构建一个新列表,而不是就地修改现有列表,
  • list 实际上可以是任何IEnumerable,不仅仅是一个 List
  • Where 方法是一种常用的、文档齐全的扩展方法,任何合理的方法都可以使用-熟练C# 程序员应该一眼就能认出,
  • 任何阅读该代码的人都清楚它正在创建一个新列表,
  • 如果您不想创建一个新列表,只需省略 ToList () 并枚举结果

我真的很难想象我想要为采用谓词的 IEnumerable 编写扩展方法的情况。如果您不使用 Where(),那么您节省的费用就很少。

As boca observed, List<T> already has a method to do this. A somewhat larger issue, though, is that this really isn't a scenario where you should be creating a new extension method. There's already an extension method that takes a predicate: Where.

Granted, doing this:

var result = list.Where(x => x != 5).ToList();

is a little more code than using RemoveAll:

list.RemoveAll(x => x == 5);

But:

  • it also builds a new list instead of modifying the existing list in place,
  • list can actually be any IEnumerable<T>, not just a List<T>,
  • the Where method is a commonly used, well-documented extension method that any reasonably-skilled C# programmer can be expected to recognize on sight
  • it's clear to anyone reading that code that it's creating a new list, and
  • if you don't want to create a new list, just leave off ToList() and enumerate over result.

It's really hard for me to envision circumstances where I'd want to write an extension method for IEnumerable<T> that takes a predicate. You're saving very little by making it possible for you to not use Where().

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