【问题标题】:Generic solution to compare two generic list and type known only on run time比较两个通用列表和类型的通用解决方案,仅在运行时知道
【发布时间】:2017-10-10 09:18:59
【问题描述】:

我浏览过很多帖子都回答了这个问题。但问题是我有两个通用列表,其类型将在运行时知道,其次我需要将一个列表的所有列与另一个列表的所有列进行比较。唯一统一的是这两个列表将是相同的类型。

对于不同类型的列表,这个操作要执行 27 次。

所以我需要一个通用的解决方案来比较这两个列表。需要任何进一步的细节,请告诉。但这对我很重要。

 private void CompareTwoObjects(IList dataFromExcel, IList dataFromTable)
        {
            foreach (var objExcel in dataFromExcel)
            {

            }
        }

完全希望是这样的。我不知道。也许这可以帮助您获得真正需要的东西。

【问题讨论】:

  • 你是否为所有类型实现了 Equals() 函数并使用它?
  • 我认为唯一可能的解决方案是在这里使用反射
  • 是的,我知道要使用反射,但如何使用 linq 比较属性。因为我需要将一个列表的记录与其他列表的所有记录进行比较。我正在考虑使用 .Any()

标签: c# .net generics


【解决方案1】:

您最简单的解决方案是在您的 27 种不同类型上实现 IEquatable<T>。然后您可以使用常规的等号运算符(dataFromExcel.Equals(dataFromTable)dataFromExcel == dataFromTable。但是,如果您需要在此过程中对这些值执行任何操作,您还有其他选择。

使用来自this answer 的想法,您无需使用反射即可获得此信息。利用 Newtonsoft JSON.NET 库为您完成“繁重的工作”,并让您的代码保持可读性。

您想要做的一件事是将每个列表的类型限制为相同的类型。你的方法看起来像这样:

private bool CompareTwoObjects<T>(T one, T two)
{
    var json1 = JObject.FromObject(one);
    var json2 = JObject.FromObject(two);

    foreach (JProperty prop1 in json1.Properties())
    {
        var prop2 = json2.Properties().First(p => p.Name == prop1.Name);

        if (prop1.Value != prop2.Value)
        {
            return false;
        }
    }

    return true;
}

在您的评论中看到您想要比较每个的集合,您仍然可以使用这两个选项。

IEquatable&lt;T&gt;方法:

var allAreEqual = dataFromExcel.All(one => dataFromTable.Any(two => one == two));

自定义方法:

var allAreEqual = dataFromExcel(one => dataFromTable.Any(two => CompareTwoObjects(one, two));

我确信您可以在此处进行一些优化以减少 N 因子,但这为您指明了正确的方向。

【讨论】:

  • For var allAreEqual = dataFromExcel.All(one => dataFromTable.Any(two => one == two));我得到的不包含所有的定义。在第二个中,我们没有得到 JObject 使用哪个库
  • @AnirudhAgarwal 您的dataFromExceldataFromTable.Any().All() 方法需要是对象的集合。
  • @AnirudhAgarwal JObject 库来自我在回答之前提到的 Newtonsoft JSON.NET 库。
  • 感谢您的帮助,在您的回答的帮助下我得到了答案
【解决方案2】:

我不确定这个解决方案(因为性能和可序列化类型),但您可能可以将集合序列化为 JSON(例如)并比较字符串。请注意,在这种情况下,集合由不同类型关闭,例如 List&lt;TypeForCompare1&gt;()List&lt;TypeForCompare2&gt;() 可以与当前实现相同。尽管如此,它很容易尝试,也许对你来说就足够了。

class Type1
{
    public int Prop1 { get; set; }
    public string Prop2 { get; set; }
}

class TypeForCompare1
{
    public Type1 Prop1 { get; set; }
    public double Prop2 { get; set; }
}

class TypeForCompare2
{
    public Type1 Prop1 { get; set; }
    public double Prop2 { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var List1 = new List<int>() { 1, 2 };
        var List2 = new List<int>() { 1, 2, 3 };

        var List3 = new List<TypeForCompare1>() {
            new TypeForCompare1() { Prop1 = new Type1 { Prop1 = 1, Prop2 = "test" }, Prop2 = 1.23 },
        };

        var List4 = new List<TypeForCompare2>() {
            new TypeForCompare2() { Prop1 = new Type1 { Prop1 = 1, Prop2 = "test" }, Prop2 = 1.23 },
        };

        Console.WriteLine(CompareTwoObjects(List1, List2));
        Console.WriteLine(CompareTwoObjects(List3, List4));

        Console.ReadLine();
    }

    static bool CompareTwoObjects(IList obj1, IList obj2)
    {
        var JsonObj1 = new JavaScriptSerializer().Serialize(obj1);
        var JsonObj2 = new JavaScriptSerializer().Serialize(obj2);
        return JsonObj1 == JsonObj2;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    相关资源
    最近更新 更多