C# 如何连接两个不同的列表,它们都有相同的基类?

C# 如何连接两个不同的列表,它们都有相同的基类?,c#,generics,collections,C#,Generics,Collections,我有一个名为ItemChange的类,它如下所示: public class ItemChange<T> where T : MyBase { public DateTime When { get; set; } public string Who { get; set; } public T NewState; public T OldState; } 正如您所看到的,我需要连接来自多个类型的更改,但是我想获取numberOfChanges定义的最

我有一个名为ItemChange的类,它如下所示:

public class ItemChange<T> where T : MyBase
{
    public DateTime When { get; set; }
    public string Who { get; set; }
    public T NewState;
    public T OldState;
}
正如您所看到的,我需要连接来自多个类型的更改,但是我想获取numberOfChanges定义的最新更改数

任何关于如何让下面的代码工作的建议,因为Concat行给了我一个编译器错误,我想我必须以某种特殊的方式来实现它


有什么办法吗?

这个怎么样?我不确定,因为我现在不能测试它

public IEnumerable<ItemChange<T>> GetChangeHistory<T>(int numberOfChanges) where T : MyBase
{
    IEnumerable<ItemChange<MyBase>> obj1Changes = GetChanges<Object1>().Select(i => new ItemChange<MyBase>(){ When = i.When, Who = i.Who, NewState = i.NewState, OldState = i.OldState });
    IEnumerable<ItemChange<MyBase>> obj1Changes = GetChanges<Object2>().Select(i => new ItemChange<MyBase>(){ When = i.When, Who = i.Who, NewState = i.NewState, OldState = i.OldState });
    return obj1Changes.Concat(obj2Changes).OrderByDescending(r => r.When).Take(numberofChanges);
}
它从ItemChange或ItemChange创建ItemChange的新实例


根据您的使用情况,您可能希望在Linq的末尾添加.ToList以提高性能。

您尝试的操作并不安全,因为ItemChange和ItemChange之间没有转换,当然也没有转换到任意ItemChange。您最好尝试执行ItemChange,但类在C中不是协变的,因此这是无效的:

ItemChange<MyBase> change = new ItemChange<Object1>();

我建议为ItemChange添加一个名为ItemChange的基类。ItemChange可以声明When属性。然后,将列表内容强制转换为concat和orderby的基本ItemChange就变得非常容易了

using System;
using System.Collections.Generic;
using System.Linq;

namespace brosell
{

public class MyBase
{

}

public class ItemChange
{
    public DateTime When { get; set; }

}

public class ItemChange<T>: ItemChange where T : MyBase
{
    public string Who { get; set; }
    public T NewState;
    public T OldState;
}

public class Sub1: MyBase
{

}

public class Sub2: MyBase
{

}

   public class HelloWorld
   {
    public static void Main(string[] args)
    {
        List<ItemChange<Sub1>> listOfSub1 = new List<ItemChange<Sub1>>();
        List<ItemChange<Sub2>> listOfSub2 = new List<ItemChange<Sub2>>();

        var concated = listOfSub1.Cast<ItemChange>().Concat(listOfSub2.Cast<ItemChange>());

        var filtered = concated.OrderByDescending(ic => ic.When).Take(10);  

        Console.WriteLine("{0}", filtered.Count());
        }
   } 
}

如果您定义了一个接口IReadableItemChange,它公开了T类型的只读属性而不是该类型的字段,并且如果ItemChange实现了IReadableItemChange,那么ItemChange和ItemChange都将实现IReadableItemChange,顺便说一句,IReadableItemChange用于任何基类型,例如Derived1:baseType和Derived2:baseType。ItemChange的构造函数接受IReadableItemChange并从中复制数据可能也会很有帮助。

请参阅。您是否尝试强制转换为IEnumerableobj2Changes?可能是类似的情况?返回obj1Changes.Cast.Concatobj2Changes.Cast.orderbydressingr=>r.When.TakenumberofChanges;当然,现在的挑战是弄清楚最终过滤列表实际包含的内容!我会考虑重构架构以更好地表示业务逻辑。例如,为什么ItemChange甚至需要知道发生了什么变化?
public interface IItemChange<out T> where T : MyBase
{
    DateTime When { get; set; }
    string Who { get; set; }
    T NewState { get; }
    T OldState { get; }
}

public class ItemChange<T> : IItemChange<T> where T : MyBase
{
    public DateTime When { get; set; }
    public string Who { get; set; }
    public T NewState { get; set; }
    public T OldState { get; set; }
}
private static IEnumerable<IItemChange<T>> GetChanges<T>() where T : MyBase { ... }

public static IEnumerable<IItemChange<MyBase>> GetChangeHistory(int numberOfChanges)
{
    IEnumerable<IItemChange<MyBase>> obj1Changes = GetChanges<Object1>();
    IEnumerable<IItemChange<MyBase>> obj2Changes = GetChanges<Object2>();
    return obj1Changes.Concat(obj2Changes).OrderByDescending(r => r.When).Take(numberOfChanges);
}
using System;
using System.Collections.Generic;
using System.Linq;

namespace brosell
{

public class MyBase
{

}

public class ItemChange
{
    public DateTime When { get; set; }

}

public class ItemChange<T>: ItemChange where T : MyBase
{
    public string Who { get; set; }
    public T NewState;
    public T OldState;
}

public class Sub1: MyBase
{

}

public class Sub2: MyBase
{

}

   public class HelloWorld
   {
    public static void Main(string[] args)
    {
        List<ItemChange<Sub1>> listOfSub1 = new List<ItemChange<Sub1>>();
        List<ItemChange<Sub2>> listOfSub2 = new List<ItemChange<Sub2>>();

        var concated = listOfSub1.Cast<ItemChange>().Concat(listOfSub2.Cast<ItemChange>());

        var filtered = concated.OrderByDescending(ic => ic.When).Take(10);  

        Console.WriteLine("{0}", filtered.Count());
        }
   } 
}