C# 传递 Func> 数组到一个方法

发布于 2024-10-22 02:34:37 字数 3638 浏览 6 评论 0 原文

我的第一篇(也是非常可怕的帖子)如下。

我尝试做一个完整的例子,我想要得到什么。我希望这能得到更好的解释。

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Boy> boys = new List<Boy>();
            boys.Add(new Boy("Jhon", 7));
            boys.Add(new Boy("Oscar", 6));
            boys.Add(new Boy("Oscar", 7));
            boys.Add(new Boy("Peter", 5));
            ClassRoom myClass = new ClassRoom(boys);

            Console.WriteLine(myClass.ByName("Oscar").Count);  // Prints 2
            Console.WriteLine(myClass.ByYearsOld(7).Count);  // Prints 2

            // This has errors...................
            // But this is as I would like to call my BySomeConditions method....
            Console.WriteLine(  // It should print 1
                                myClass.BySomeConditions([myClass.ByName("Oscar"),
                                                          myClass.ByYearsOld(7)]
                                                        )
                             );
            Console.ReadKey();
        }





        class ClassRoom
        {
            private List<Boy> students;

            public ClassRoom(List<Boy> students)
            {
                this.students = students;
            }

            public List<Boy> ByName(string name)
            {
                return students.FindAll(x => x.Name == name);
            }
            public List<Boy> ByYearsOld(int yearsOld)
            {
                return students.FindAll(x => x.YearsOld == yearsOld);
            }

            // This has ERRORS.......................
            public List<Boy> BySomeConditions(params Func<X, List<Boy>>[] conditions)
            {
                IEnumerable<Boy> result = students;                
                foreach (var condition in conditions) {
                    // I want it ONLY be called with existent functions (ByName and/or ByYearsOld)
                    result = result.Intersect(condition(this));  
                }
            }
        }


        class Boy
        {
            public string Name { get; set; }
            public int YearsOld { get; set; }
            public Boy(string name, int yearsOld)
            {
                Name = name;
                YearsOld = yearsOld;
            }
        }
    }
}

==============第一篇文章===================== 您好,

我有一个带有方法的类:

public class X
{
    private readonly List<string> myList;

    public X(List<string> paramList) // string is really an object
    {
         myList = paramList;
    }

    // Now I want this...
    public List<string> CheckConditions(params Func<T, List<string>>[] conditions)
    {
         var result = myList;
         foreach (Func<T, List<string>> condition in conditions)
         {
               result = result.Intersect(condition(T));
         }
    }

    public List<string> check1(string S)
    {
         return myList.FindAll(x => x.FieldS == S);
    }
    public List<string> check1(int I)
    {
         return myList.FindAll(x => x.FieldI == I);
    }
}

抱歉,如果有一些错误,我是从头开始编写的,以避免复杂的实际情况。

我想要的是像这样调用我的方法:

   X.check1("Jhon");

or

   X.check2(12);

or (这是我问题的目标):

   X.CheckConditions(X.check1("Jhon"), X.chek2(12));

感谢并抱歉我的糟糕例子......

My first (and really horrible post) is below.

I try to do a complete example what I want to get. I hope this will be left explained a bit better.

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Boy> boys = new List<Boy>();
            boys.Add(new Boy("Jhon", 7));
            boys.Add(new Boy("Oscar", 6));
            boys.Add(new Boy("Oscar", 7));
            boys.Add(new Boy("Peter", 5));
            ClassRoom myClass = new ClassRoom(boys);

            Console.WriteLine(myClass.ByName("Oscar").Count);  // Prints 2
            Console.WriteLine(myClass.ByYearsOld(7).Count);  // Prints 2

            // This has errors...................
            // But this is as I would like to call my BySomeConditions method....
            Console.WriteLine(  // It should print 1
                                myClass.BySomeConditions([myClass.ByName("Oscar"),
                                                          myClass.ByYearsOld(7)]
                                                        )
                             );
            Console.ReadKey();
        }





        class ClassRoom
        {
            private List<Boy> students;

            public ClassRoom(List<Boy> students)
            {
                this.students = students;
            }

            public List<Boy> ByName(string name)
            {
                return students.FindAll(x => x.Name == name);
            }
            public List<Boy> ByYearsOld(int yearsOld)
            {
                return students.FindAll(x => x.YearsOld == yearsOld);
            }

            // This has ERRORS.......................
            public List<Boy> BySomeConditions(params Func<X, List<Boy>>[] conditions)
            {
                IEnumerable<Boy> result = students;                
                foreach (var condition in conditions) {
                    // I want it ONLY be called with existent functions (ByName and/or ByYearsOld)
                    result = result.Intersect(condition(this));  
                }
            }
        }


        class Boy
        {
            public string Name { get; set; }
            public int YearsOld { get; set; }
            public Boy(string name, int yearsOld)
            {
                Name = name;
                YearsOld = yearsOld;
            }
        }
    }
}

============== first post =====================
Hello,

I have a class with methods:

public class X
{
    private readonly List<string> myList;

    public X(List<string> paramList) // string is really an object
    {
         myList = paramList;
    }

    // Now I want this...
    public List<string> CheckConditions(params Func<T, List<string>>[] conditions)
    {
         var result = myList;
         foreach (Func<T, List<string>> condition in conditions)
         {
               result = result.Intersect(condition(T));
         }
    }

    public List<string> check1(string S)
    {
         return myList.FindAll(x => x.FieldS == S);
    }
    public List<string> check1(int I)
    {
         return myList.FindAll(x => x.FieldI == I);
    }
}

Sorry if there is some error, I have written from scrach to avoid complex real case.

What I want is call my methods like this:

   X.check1("Jhon");

or

   X.check2(12);

or (this is the goal of my question):

   X.CheckConditions(X.check1("Jhon"), X.chek2(12));

Thanks and sorry by my poor example...

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

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

发布评论

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

评论(5

岁月静好 2024-10-29 02:34:38

您可以将函数重写为如下所示:

// Now I want this...
    public List<string> CheckConditions(params Func<T, List<string>>[] conditions)
    {
         var result = myList;
         foreach (Func<T, List<string>> condition in conditions)
         {
               result = result.Intersect(condition(T));
         }
    }

您的调用将是 X.CheckConditions(()=>X.check1("Jhon"), ()=>X.chek2(12));< /code>

并且您需要为 x 提供一个实例(因为这些方法是实例方法而不是静态方法)

在您的示例中,您将 T 作为参数传递给函子,但 T 是类型参数,因此不能将其传递为该方法的参数。你的意思是传递一个值吗?

这就要求您澄清为什么要这样做。也许如果您提供有关您想要完成的任务(而不是如何完成)的详细信息,那么您可以获得更好的问题解决方案。

you could rewrite you function to look like this:

// Now I want this...
    public List<string> CheckConditions(params Func<T, List<string>>[] conditions)
    {
         var result = myList;
         foreach (Func<T, List<string>> condition in conditions)
         {
               result = result.Intersect(condition(T));
         }
    }

your call would then be X.CheckConditions(()=>X.check1("Jhon"), ()=>X.chek2(12));

and you need to provide an instance for x (since the methods are instance methods and not static methods)

In your example you pass T as an argument to the functor but T is a type argument som it can't be passed as an argument to the method. Did you mean to pass a value?

This begs for a clarification of why you would want to do this. Maybe if you provided details on what you are trying to accomplish (as opposed to how) then you could get a better solution to your problem.

青朷 2024-10-29 02:34:38

您传递给您的

X.CheckConditions

不是对函数的引用,而是它们调用的返回值。

现在,如果您传递函数引用 - 它不带有参数,除非您构造并传递一个将包含函数引用及其应处理的参数的数据结构

在这种情况下 - 泛型不是解决方案。您应该考虑遵循另一种模式,例如命令模式或策略模式,在其中传递给检查器对象的 CheckConstruction 实例,每个实例都使用它应该使用的参数进行实例化,并且要么实现要么是由验证函数提供。

What you pass to your

X.CheckConditions

is not a reference to the functions, but the returned value of their invocation.

Now, if you pass function reference - it does not come with parameters, unless you construct and pass a data-structure that will contain the function reference and the arguments it should work on.

In this case - generics is not the solution. You should consider another pattern to follow, like command pattern or strategy pattern, where you pass to your CheckConstruction instances of checker-objects, each is instantiated with the parameters it should work on, and either implements or is provided by the validation function.

〃安静 2024-10-29 02:34:37

目前还不清楚你的 T 来自哪里。

这满足您的要求吗?

public class X<T>
{
  private List<T> myList;

  public List<T> CheckConditions(params Func<T, bool>[] conditions)
  {
    IEnumerable<T> query = myList;
    foreach (Func<T, bool> condition in conditions)
    {
      query = query.Where(condition);
    }
    return query.ToList();
  }
}

然后后来:

List<T> result = X.CheckConditions(
  z => z.FieldS == "Jhon",
  z => z.FieldI == 12
);

It is unclear where your T comes from.

Does this meet your requirements?

public class X<T>
{
  private List<T> myList;

  public List<T> CheckConditions(params Func<T, bool>[] conditions)
  {
    IEnumerable<T> query = myList;
    foreach (Func<T, bool> condition in conditions)
    {
      query = query.Where(condition);
    }
    return query.ToList();
  }
}

Then later:

List<T> result = X.CheckConditions(
  z => z.FieldS == "Jhon",
  z => z.FieldI == 12
);
梦情居士 2024-10-29 02:34:37

您需要更改 CheckConditions 的方法签名,它接受可变数量的 List,而不是函数。

public List<string> CheckConditions(params List<string>[] lists)

check1 的返回类型是 List,因此它需要是 CheckConditions 接受的参数类型。

You need to change the method signature of CheckConditions, it's accepting a variable number of List<string>, not functions.

public List<string> CheckConditions(params List<string>[] lists)

The return type of check1 is List<string>, so that needs to be the type of the parameter that CheckConditions accepts.

故事灯 2024-10-29 02:34:37

没有理由使其通用,您知道您想要对 X 的当前实例进行操作(因此传入 this,而不是 T 类型参数)。您需要清理一些东西才能编译(返回 result 并使 result 的类型与 Intersect 调用兼容)。您可以这样定义它:

public List<string> CheckConditions(params Func<X, List<string>>[] conditions)
{
     IEnumerable<string> result = myList;
     foreach (var condition in conditions)
     {
           result = result.Intersect(condition(this));
     }

     return result.ToList();
}

Ant 然后这样调用它:

xInstance.CheckConditions(x => x.check1("JHon"), x => x.check1(12));

话虽如此,我不确定为什么您不只是传递这些函数的结果,而不是传递实际的函数:

public List<string> CheckConditions(params List<string>[] conditions)
{
     IEnumerable<string> result = myList;
     foreach (var condition in conditions)
     {
           result = result.Intersect(condition);
     }

     return result.ToList();
}

然后像这样调用它您的示例,而不是传入 lambda 表达式。

There's no reason to make it generic, you know that you want to operate on the current instance of X (so pass in this, instead of the T type parameter). You need to cleanup a few things to to get it to compile (return result and make the type of result and the Intersect call compatible). You can define it like this:

public List<string> CheckConditions(params Func<X, List<string>>[] conditions)
{
     IEnumerable<string> result = myList;
     foreach (var condition in conditions)
     {
           result = result.Intersect(condition(this));
     }

     return result.ToList();
}

Ant then call it like this:

xInstance.CheckConditions(x => x.check1("JHon"), x => x.check1(12));

All that said, I'm not sure why you wouldn't just pass around the results of these functions, instead of passing the actual functions around:

public List<string> CheckConditions(params List<string>[] conditions)
{
     IEnumerable<string> result = myList;
     foreach (var condition in conditions)
     {
           result = result.Intersect(condition);
     }

     return result.ToList();
}

Then call it as in your example, rather than passing in lambda expressions.

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