如何通过继承类的 DateTime 属性对 List 进行排序?

3
考虑以下情况。我有一个基类Measurement和几个派生类(例如AdditionalMeasurementSpecialMeasurement),它们是从Measurement继承的。
class Measurement {
   public DateTime TimeStamp { get; set; }
}

class AdditionalMeasurement : Measurement {
   public DateTime PurchaseDate { get; set; }
}

class SpecialMeasurement: Measurement {
   public DateTime PrescriptionDate { get; set; }
}

如何按默认方式(对于所有其他派生类)将 List<Measurement>Measurement.TimeStamp 降序排序,但如果列表中的项是 AdditionalMeasurement 类型,则按 PurchaseDate 排序,如果项是 SpecialMeasurement 类型,则按 PrescriptionDate 排序?

显然,我下面的尝试行不通,但希望能表达出思想。

List<Measurement> measurements = new List<Measurement>() { ... };
measurements.OrderByDescending(m =>
{
    if (m is AdditionalMeasurement additionalMeasurement)
    {
        return additionalMeasurement.PurchaseDate;
    }
    else if (m is SpecialMeasurement specialMeasurement)
    {
        return specialMeasurement.PrescriptionDate;
    }
    else
    {
        return m.TimeStamp;
    }
});

可以请您分享一些样本数据和期望的输出顺序吗? - Guru Stron
3
你应该编写/覆盖一个getOrderDateTime函数,这就是面向对象编程的用途... - Turo
  1. 你可以像这个例子中那样实现自己的比较器,并在其中放入你独特的逻辑。
  2. 你可以在Measurement中创建一个虚方法,可以在派生类中重写,并返回所需的属性。
- Mong Zhu
3个回答

6
经典的面向对象编程方式是让每个类自己定义/重写其排序准则:
using System;

class Measurement {
   public DateTime TimeStamp { get; set; }

   public virtual DateTime SortDate => this.TimeStamp;
}

class AdditionalMeasurement : Measurement {
   public DateTime PurchaseDate { get; set; }
    
    public override DateTime SortDate => this.PurchaseDate;
}

class SpecialMeasurement: Measurement {
   public DateTime PrescriptionDate { get; set; }
    
    public override DateTime SortDate => this.PrescriptionDate;
}

                    
public class Program
{
    public static void Main()
    {
        var measurements = new List<Measurement>() { };

        var ordered = measurements.OrderBy(m => m.SortDate).ToList();

    }
}

您的具体问题可能是OrderBy返回一个有序的可枚举对象,而不会对现有列表进行排序。您没有使用返回值进行调用表明您可能不知道这一点。提高编译器的警告级别,这应该会生成一个编译器警告。

您可以使用List<T>Sort方法来原地对列表进行排序,然后您可以将决定使用哪个日期进行排序的逻辑放在一个Comparer类中。如果您有多种不同的排序逻辑,这可能会很有帮助。


1
虽然这看起来很不错,但我没有接受这个答案,因为我不想仅仅为了执行某种排序而修改类。 - Behemoth

3
如果你不想像nvoigt建议的那样改变类,这段代码更短,并且正确地使用了ToList并将结果分配给原始列表。
measurements = measurements.OrderByDescending(m => m switch
{
    AdditionalMeasurement additionalMeasurement => additionalMeasurement.PurchaseDate,
    SpecialMeasurement specialMeasurement => specialMeasurement.PrescriptionDate,
    _ => m.TimeStamp
}).ToList()

所以你的代码问题主要是你没有使用从OrderByDescending返回的IEnumerable<Measurement>来创建一个新的列表(ToList)。

0
你可以尝试使用 TimeStamp 作为默认比较器对列表进行排序,然后反转数组以获取按降序排列的 Measurement 对象列表。
//sort the objects in the list ascendingly
list.Sort((x,y)=> x.TimeStamp.CompareTo(y.TimeStamp));
//reverse the order of Measurement objects
list.Reverse();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接