【问题标题】:Merge 2 lists of 2 different types (alternatives)合并 2 个不同类型的 2 个列表(替代方案)
【发布时间】:2013-03-24 10:10:35
【问题描述】:

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

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

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

【问题讨论】:

  • 第一个属性是什么意思?
  • 我有 2 个列表:list1 list2 每个类都有很多属性,所以第一个属性是列表中每个对象的主键

标签: linq list join merge


【解决方案1】:
var foo = (from type1 in list1
           join type2 in list2 on type1.Id equals type2.Id
           select new {type1, type2}).ToList();

【讨论】:

  • 感谢您的回答,但是,如果我不知道每个类的 First 属性的名称怎么办?
【解决方案2】:

通过说“属性”,我假设您引用的是属性或字段。 请不要使用“属性”,因为这会造成混淆并且意味着完全不同的东西:

[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(很少见,但可能)怎么办?等等

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

【讨论】:

    猜你喜欢
    • 2015-04-10
    • 2016-08-14
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 2022-06-28
    相关资源
    最近更新 更多