Skip to main content
 首页 » 编程设计

c#之在通用集合上使用 Except()

2024年02月24日31telwanggs

我问过这个question关于使用从通用集合返回一个对象(First、Min、Max 等)的 Linq 方法。 我现在希望能够使用 linq 的 Except() 方法,但我不确定该怎么做。也许答案就在我面前,但我认为我需要帮助。
我有一个通用方法,可以为相应的描述字段填写缺失的日期。该方法声明如下:

public IEnumerable<T> FillInMissingDates<T>(IEnumerable<T> collection, string datePropertyName, string descriptionPropertyName) 
    { 
       Type type = typeof(T); 
       PropertyInfo dateProperty = type.GetProperty(datePropertyName); 
       PropertyInfo descriptionProperty = type.GetProperty(descriptionPropertyName); 
       ... 
    } 

我要完成的是这个。 datePropertyName 是我将用来填补日期空白的日期属性的名称(为集合中尚不存在的日期添加默认对象实例)。如果我正在处理一个非泛型类,我会这样做:

foreach (string description in descriptions) 
{ 
    var missingDates = allDates.Except(originalData.Where(d => d.Description == desc).Select(d => d.TransactionDate).ToList()); 
... 
} 

但是我如何使用泛型方法 FillInMissingDates 以及在运行时解析的 dateProperty 和 descriptionProperty 属性来做同样的事情?

请您参考如下方法:

我认为最好的方法是定义一个接口(interface),其中包含您要在方法中使用的所有属性。具有该方法可用于实现该接口(interface)的类。然后,使用泛型方法并约束泛型类型从接口(interface)派生。

此示例可能无法完全满足您的要求——它会为列表中与描述匹配的项目填充缺少的日期,但希望它能为您提供基本思路。

 public interface ITransactable 
 { 
     string Description { get; } 
     DateTime? TransactionDate { get; } 
 } 
 
 public class CompletedTransaction : ITransactable 
 { 
     ... 
 } 
 
 // note conversion to extension method 
 public static void FillInMissingDates<T>( this IEnumerable<T> collection,  
                                           string match, 
                                           DateTime defaultDate ) 
        where T : ITransactable 
 { 
      foreach (var trans in collection.Where( t => t.Description = match )) 
      { 
          if (!trans.TransactionDate.HasValue) 
          { 
              trans.TransactionDate = defaultDate; 
          } 
      } 
 } 

您需要在调用之前将您的枚举转换为 ITransactable(至少在 C# 4.0 发布之前)。

 var list = new List<CompletedTransaction>(); 
 
 list.Cast<ITransactable>() 
     .FillInMissingDates("description",DateTime.MinValue); 

或者,您可以使用 Dynamic LINQ 进行调查来自 VS2008 Samples收藏。如果类之间不一致,这将允许您指定属性的名称。但是,您可能仍需要使用反射来设置属性。