C# 如何连接两个不同的列表,它们都有相同的基类?
我有一个名为ItemChange的类,它如下所示: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定义的最
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());
}
}
}