1

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

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

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

4

2 回答 2

0
var foo = (from type1 in list1
           join type2 in list2 on type1.Id equals type2.Id
           select new {type1, type2}).ToList();
于 2013-04-03T01:22:30.727 回答
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();

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

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;
}

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

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

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

于 2013-04-03T20:32:31.767 回答