C# 如何在泛型方法中筛选集合

C# 如何在泛型方法中筛选集合,c#,.net,generics,generic-collections,C#,.net,Generics,Generic Collections,我有一个两个类,它具有以下属性 Class A { public int CustID { get; set; } public bool isProcessed { get; set; } } Class B { public int EmpId{ get; set; } public bool isProcessed { get; set; } } 我创建了一个接受所有这些类的泛型方法。“isProcessed”属性在这

我有一个两个类,它具有以下属性

 Class A
  {
      public int CustID { get; set; }
      public bool isProcessed { get; set; }
  }
  Class B
  {
      public int EmpId{ get; set; }
      public bool isProcessed { get; set; }
  }
我创建了一个接受所有这些类的泛型方法。“isProcessed”属性在这两个类中都是通用的

public void ProceesData<T>(IList<T> param1, string date1)
{

}
public void ProceesData(IList param1,字符串date1)
{
}
我需要以下东西

  • 在ProcessData方法中,我想筛选具有 isProcessed标志为“True”
  • 我还想迭代这个集合,并需要为IsProcessed属性设置值
  • 注意:我更喜欢使用反射的解决方案,因为属性名是常量(即“IsProcessed”)


    有人能帮上忙吗。

    创建一个接口,如
    IProcessData
    ,它包含一个布尔属性,
    IsProcessed
    。让两个类都实现这个接口。更改
    ProcessData
    方法,使其不再具有通用符号(
    ),并接受
    IList
    。然后对param1数据执行筛选和迭代。

    创建一个接口,如
    IProcessData
    ,该接口包含一个布尔属性,
    IsProcessed
    。让两个类都实现这个接口。更改
    ProcessData
    方法,使其不再具有通用符号(
    ),并接受
    IList
    。然后对param1数据执行过滤和迭代。

    最简单的方法是确保这两个类实现一个公共接口并约束您的泛型方法。例如:

    public interface IProcessable
    {
        bool isProcessed { get; set; }
    }
    public class A : IProcessable
    {
        public int CustID { get; set; }
        public bool isProcessed { get; set; }
    }
    
    public class B : IProcessable
    {
        public int EmpId { get; set; }
        public bool isProcessed { get; set; }
    }
    
    public void ProceesData<T>(IList<T> param1, string date1, Action<T> func)
    {
        foreach (var element in param1)
        {
            func(element);
        }
    }
    
    现在,您的方法如下所示:

    public void ProceesData<T>(IList<T> param1, string date1)
        where T : IProcessable // <-- generic constraint added
    {
        foreach (var element in param1)
        {
            element.isProcessed = true;
        }
    }
    
    ProceesData<A>(list, "", x => x.isProcessed = true);
    
    ProceesData<A>(a_list, "", "isProcessed", false, true);
    
    public void ProceesData(IList param1,字符串date1)
    其中T:IProcessable//x.isProcessed=true);
    
    最简单的方法是确保两个类都实现一个公共接口并约束您的泛型方法。例如:

    public interface IProcessable
    {
        bool isProcessed { get; set; }
    }
    public class A : IProcessable
    {
        public int CustID { get; set; }
        public bool isProcessed { get; set; }
    }
    
    public class B : IProcessable
    {
        public int EmpId { get; set; }
        public bool isProcessed { get; set; }
    }
    
    public void ProceesData<T>(IList<T> param1, string date1, Action<T> func)
    {
        foreach (var element in param1)
        {
            func(element);
        }
    }
    
    现在,您的方法如下所示:

    public void ProceesData<T>(IList<T> param1, string date1)
        where T : IProcessable // <-- generic constraint added
    {
        foreach (var element in param1)
        {
            element.isProcessed = true;
        }
    }
    
    ProceesData<A>(list, "", x => x.isProcessed = true);
    
    ProceesData<A>(a_list, "", "isProcessed", false, true);
    
    public void ProceesData(IList param1,字符串date1)
    其中T:IProcessable//x.isProcessed=true);
    
    注意:我更喜欢使用反射的解决方案

    此方法将迭代集合,根据
    propertyName
    filterValue
    进行过滤,并使用反射将值设置为
    newValue

    public void ProceesData<T>(IList<T> param1, string date1, string propertyName, 
                                      object filterValue, object newValue)
    {
        PropertyInfo pi = typeof(T).GetProperty(propertyName);
    
        object value;
    
        for (int i = param1.Count; i <= 0; i--)
        {
            value = pi.GetValue(param1[i]);
            if (value.Equals(filterValue))
            {
                pi.SetValue(param1[i], newValue);
            }
        }
    }
    
    此呼叫将给您相同的结果:

    ProceesData<A>(a_list, "", (x)=> { if (!x.isProcessed) x.isProcessed = true; });
    
    对于
    操作
    重载,您必须使用
    动态
    数据类型:

    ProceesData<dynamic>(obj_list, "", (x) => { if (!x.isProcessed) obj_list.Remove(x); });
    
    ProceesData(obj_list,”,(x)=>{if(!x.isProcessed)obj_list.Remove(x);});
    
    对于做事情的反射方式,您需要在每次迭代时检查类型。这将增加处理时间

    public static void ProceesData<T>(IList<T> param1, string date1, string propertyName, object filterValue, object newValue)
    {
        for (int i = param1.Count-1; i >= 0; i--)
        {
            PropertyInfo pi = param1[i].GetType().GetProperty(propertyName);
            object value;
    
            value = pi.GetValue(param1[i]);
            if (value.Equals(filterValue))
            {
                pi.SetValue(param1[i], newValue);
            }
        }
    }
    
    publicstaticvoidproceesdata(IListparam1,stringdate1,stringpropertyname,objectfiltervalue,objectnewvalue)
    {
    对于(int i=param1.Count-1;i>=0;i--)
    {
    PropertyInfo pi=param1[i].GetType().GetProperty(propertyName);
    目标价值;
    value=pi.GetValue(param1[i]);
    if(value.Equals(filterValue))
    {
    pi.设定值(参数1[i],新值);
    }
    }
    }
    
    注意:我更喜欢使用反射的解决方案

    此方法将迭代集合,根据
    propertyName
    filterValue
    进行过滤,并使用反射将值设置为
    newValue

    public void ProceesData<T>(IList<T> param1, string date1, string propertyName, 
                                      object filterValue, object newValue)
    {
        PropertyInfo pi = typeof(T).GetProperty(propertyName);
    
        object value;
    
        for (int i = param1.Count; i <= 0; i--)
        {
            value = pi.GetValue(param1[i]);
            if (value.Equals(filterValue))
            {
                pi.SetValue(param1[i], newValue);
            }
        }
    }
    
    此呼叫将给您相同的结果:

    ProceesData<A>(a_list, "", (x)=> { if (!x.isProcessed) x.isProcessed = true; });
    
    对于
    操作
    重载,您必须使用
    动态
    数据类型:

    ProceesData<dynamic>(obj_list, "", (x) => { if (!x.isProcessed) obj_list.Remove(x); });
    
    ProceesData(obj_list,”,(x)=>{if(!x.isProcessed)obj_list.Remove(x);});
    
    对于做事情的反射方式,您需要在每次迭代时检查类型。这将增加处理时间

    public static void ProceesData<T>(IList<T> param1, string date1, string propertyName, object filterValue, object newValue)
    {
        for (int i = param1.Count-1; i >= 0; i--)
        {
            PropertyInfo pi = param1[i].GetType().GetProperty(propertyName);
            object value;
    
            value = pi.GetValue(param1[i]);
            if (value.Equals(filterValue))
            {
                pi.SetValue(param1[i], newValue);
            }
        }
    }
    
    publicstaticvoidproceesdata(IListparam1,stringdate1,stringpropertyname,objectfiltervalue,objectnewvalue)
    {
    对于(int i=param1.Count-1;i>=0;i--)
    {
    PropertyInfo pi=param1[i].GetType().GetProperty(propertyName);
    目标价值;
    value=pi.GetValue(param1[i]);
    if(value.Equals(filterValue))
    {
    pi.设定值(参数1[i],新值);
    }
    }
    }
    

    你能让
    A
    B
    实现相同的接口吗?你的类
    A
    B
    没有共同的祖先或公开接口的原因是什么?这将很容易解决问题。由于isProcessed对于类A和B是通用的,我不打算更改类结构。我认为您应该与isProcessed()方法具有通用接口,并且这两个类都应该实现它。因此,如果。
    …由于属性名称是常量
    ,那么您可以使用您的接口来代替。
    A
    B
    实现相同的接口吗?您的类
    A
    B
    没有共同的祖先或公开接口的原因是什么?这将很容易解决问题。由于isProcessed对于类A和B是通用的,我不打算更改类结构。我认为您应该与isProcessed()方法具有通用接口,并且这两个类都应该实现它。因此,如果。
    …由于属性名称是常量,我更喜欢使用反射的解决方案,因为属性名称是常量“IsProcessed”,我需要一个类似于typeof(T)的解决方案。GetProperty(“IsProcessed”)我更喜欢使用反射的解决方案,因为属性名称是常量“IsProcessed”我需要一个类似于typeof(T)的解决方案。GetProperty(“IsProcessed”)@vmb反射非常笨拙和缓慢,我不建议这样做that@GabrielNegut-如果您有一个类型为
    List
    的实例,并希望将其传递给该方法,则该操作将不起作用。@GabrielNegut:不,
    IList
    是不可协变的(它是
    IList
    而不是
    IList
    )。这意味着您可以使用IList、IList或IList调用泛型方法,但只有后者可以“转换”为IList。如果您可以使用
    IEnumerable
    而不是
    IList
    ,非泛型方法也可以正常工作。@vmb但为什么?T