合并2个不同类型的列表(替代品)

时间:2013-04-02 22:28:48

标签: linq list join merge

我在C#V4中有2个通用列表List<type1> L1List<type2> L2

我的问题:type1有一个名为“key1”的属性,type2有一个名为“key2”的属性,我想将L1和L2合并到key1 = key2上的唯一列表中。

我需要以动态方式合并它们,因为我不知道这两个类的属性,我只知道每种类型的第一个属性是主键。

2 个答案:

答案 0 :(得分:0)

var foo = (from type1 in list1
           join type2 in list2 on type1.Id equals type2.Id
           select new {type1, type2}).ToList();

答案 1 :(得分:0)

通过说'属性',我假设您正在引用属性或字段。 请不要使用“属性”,因为这会让人感到困惑并且意味着完全不同的事情:

[Attribute]
class type1
{
  public int Field;

  public int Property { get; set; }
}

因此,您有type1和type2,并希望根据类中的第一个字段或属性将它们连接到一个列表中。如果您可以知道属性的名称,最简单的实现将是使用动态(假设Prop1和Prop2属性名称):

var foo = 
(from type1 in list1
 join type2 in list2 on ((dynamic)type1).Prop1 equals ((dynamic)type2).Prop2
 select new {type1, type2}).ToList();

由于情况并非如此,我们想在类中选择“first”字段OR属性,我们唯一的方法是使用反射。如果您知道您的类中只有属性(或只有字段) - 您可以使用简单的实现:

var t1 = typeof(type1);
var t2 = typeof(type2);

//replace with .GetFields() if neccessary
var p1 = t1.GetProperties()[0]; // find first declared property of type1
var p2 = t2.GetProperties()[0]; // find first declared property of type2

var foo = (from obj1 in list1
       join obj2 in list2 on p1.GetValue(obj1,null) equals p2.GetValue(obj2,null)
       select new {obj1, obj2}).ToList();

如果字段和属性在您的类中混合,您可以使用 FindMembers(MemberTypes.Field | MemberTypes.Property ...)列出所有成员,但这种方法有问题 - 字段总是重新定位到类的开头,虽然字段顺序似乎保留,但在下面的情况下,F1将始终作为类的第一个成员返回(GetFields()将返回F1,F2和GetProperties - P1,this []):

class A
{
  public int P1 { get;set;}
  public int F1;
  public int this[int x] { get{return x;} set {} }
  public int F2;
}

此外,这种方法还存在其他问题:

  • 如果您的第一个属性是索引器怎么办? (在上面的示例中使用此[..])
  • 如果第一个字段/属性返回的对象没有为Equals实现重载怎么办?
  • 如果您的第一个属性没有实现getter(很少见,但可能),该怎么办?等

通常,这种设计(当你不知道字段/属性名称,并依赖于它们在类中的相对位置时)被认为是不好的。引用MSDN: ... GetMembers方法不按特定顺序返回成员,例如按字母顺序或声明顺序。您的代码不得依赖于返回成员的顺序,因为该顺序会有所不同。