C#传递一个Func <t,list <myclass =“”>&gt;的数组方法</t,>

时间:2011-03-11 20:39:00

标签: c# .net generics func

我的第一个(也是非常可怕的帖子)在下面。

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

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

   X.check2(12);

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

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

我的可怜的榜样感谢和抱歉...

5 个答案:

答案 0 :(得分:3)

目前还不清楚你的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
);

答案 1 :(得分:2)

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

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

check1的返回类型为List<string>,因此需要是CheckConditions接受的参数类型。

答案 2 :(得分:1)

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

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表达式。

答案 3 :(得分:0)

你传递给你的

X.CheckConditions

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

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

在这种情况下 - 泛型不是解决方案。你应该考虑另一种模式,比如命令模式或策略模式,你传递给检查器对象的CheckConstruction个实例,每个模式都用它应该处理的参数实例化,并且实现或由验证功能。

答案 4 :(得分:0)

你可以改写你的功能看起来像这样:

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

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

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

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