As noted you can't merge two disparate class types without resorting to using the object class, which I'd recommend against as it is a potential source of introducing bugs.
Better to give each class a base interface and work with a list based on that.
You then need to compare your property type in order to determine how best to sort it.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<ClassA> listA = new List<ClassA>()
{
new ClassA(){Id=1, JoinDate = new DateTime(2013, 6, 1, 12, 32, 30)},
new ClassA(){Id=2, JoinDate = new DateTime(2021, 7, 2, 12, 32, 30)},
};
List<ClassB> listB = new List<ClassB>()
{
new ClassB(){UniqueId=23, JoinDate = new DateTime(2021, 2, 6, 8, 32, 30)},
new ClassB(){UniqueId=47, JoinDate = new DateTime(2017, 2, 6, 8, 32, 30)},
};
List<IJoinDate> listJoinDate = new List<IJoinDate>();
foreach(var item in listA)
{
listJoinDate.Add(item);
}
foreach(var item in listB)
{
listJoinDate.Add(item);
}
listJoinDate.Sort((x,y)=>
{
if (x.JoinDate == null && y.JoinDate == null) return 0;
else if (x.JoinDate == null) return -1;
else if (y.JoinDate == null) return 1;
else return x.JoinDate.CompareTo(y.JoinDate);
});
Console.WriteLine("Total records = %d", listJoinDate.Count);
foreach(var item in listJoinDate)
{
Console.WriteLine(item.JoinDate);
}
Console.WriteLine("Linq OrderByDescending");
listJoinDate.AsQueryable().OrderByDescending(x=>x.JoinDate);
foreach(var item in listJoinDate)
{
Console.WriteLine(item.JoinDate);
}
Console.WriteLine("Linq OrderBy");
listJoinDate.AsQueryable().OrderBy(x=>x.JoinDate);
foreach(var item in listJoinDate)
{
Console.WriteLine(item.JoinDate);
}
}
}
public interface IJoinDate
{
DateTime JoinDate{get;set;}
}
public class ClassA :IJoinDate
{
public int Id{get;set;}
public DateTime JoinDate{get;set;}
}
public class ClassB :IJoinDate
{
public int UniqueId{get;set;}
public DateTime JoinDate{get;set;}
public string Name{get;set;}
}