快速比较两个对象的属性c#

时间:2013-01-22 20:28:44

标签: c# performance linq comparison

我有两个具有不同值的相同类型的对象:

    public class Itemi
    {
    public Itemi()
    {

    }

    public int Prop1Min { get; set; }
    public int Prop1Max { get; set; }

    public int Prop2Min { get; set; }
    public int Prop2Max { get; set; }

    public int Prop3Min { get; set; }
    public int Prop3Max { get; set; }
    ...................................
    public int Prop25Min { get; set; }
    public int Prop25Max { get; set; }

    }

现在我实例化这个类型的两个对象,并为它们的属性添加一些值。

Itemi myItem1 = new Itemi();

myItem1.Prop1Min = 1;
myItem1.Prop1Max = 4;

myItem1.Prop2Min = 2;
myItem1.Prop2Max = 4;

myItem1.Prop3Min = -1;
myItem1.Prop3Max = 5;

.............................

myItem1.Prop25Min = 1;
myItem1.Prop25Max = 5;

Itemi myItem2 = new Itemi();

myItem2.Prop1Min = 1;
myItem2.Prop1Max = 5;

myItem2.Prop2Min = -10;
myItem2.Prop2Max = 3;

myItem2.Prop3Min = 0;
myItem2.Prop3Max = 2;

................................

myItem2.Prop25Min = 3;
myItem2.Prop25Max = 6;

进行此比较的最佳和最快方法是什么:

  • 从myItem1获取每个属性,并检查Prop1-25 Min和Max中的值是否在myItem2 Prop1-25 Min和Max
  • 的范围值内

示例:

   myItem1.Prop1Min = 1
   myItem1.Prop1Max = 4

   myItem2.Prop1Min = 1
   myItem2.Prop1Max = 5

这是真的,因为mtItem1 Prop1 min和max在myItem2 min和max。

的范围内

条件应该是所有属性之间的AND,所以在我们检查所有25个属性之后,如果所有属性都在第二个对象的范围内,我们返回true。

使用Linq或其他算法除了传统的if-else外还有一种快速的方法吗?

4 个答案:

答案 0 :(得分:3)

我会将属性重构为更多:

public class Item
{
    public List<Range> Ranges { get; set; }
}

public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }
}

然后您的比较方法可能是:

if (myItem1.Ranges.Count != myItem2.Ranges.Count)
{
    return false;
}

for (int i = 0; i < myItem1.Ranges.Count; i++)
{
    if (myItem1.Ranges[i].Min < myItem2.Ranges[i].Min ||
        myItem1.Ranges[i].Max > myItem2.Ranges[i].Max)
    {
        return false;
    }
}        
return true;

否则你将不得不使用反射,这是快速的。

答案 1 :(得分:0)

Linq正在使用标准语句,如果...那么,对于每一个,没有魔法:)

如果最终目标只是比较,而不需要说明哪些属性不在范围内,那么你不需要全部检查它们,在第一个不平等的你可以结束检查。

因为你有这么多属性,所以你必须考虑将它保存在Dictionary或List中。或者使用动态属性(ITypedList),如果它将用于绑定。

答案 2 :(得分:0)

你真的应该做像Ginosaji提议的那样。

但是如果你想要使用当前的数据模型,我将采用以下方法解决问题。快乐的打字。 :)

public static bool RangeIsContained(int outerMin, int outerMax, int innerMin, int innerMax)
{
    return (outerMin <= innerMin && outerMax >= innerMax);
}

public bool IsContained(Itemi outer, Itemi inner)
{
    return RangeIsContained(outer.Prop1Min, outer.Prop1Max, inner.Prop1Min, inner.Prop1Max)
        && RangeIsContained(outer.Prop2Min, outer.Prop2Max, inner.Prop2Min, inner.Prop2Max)
        // ...
        && RangeIsContained(outer.Prop25Min, outer.Prop25Max, inner.Prop25Min, inner.Prop25Max);
}

使用您的数据模型,这基本上是唯一的方法,除了反射(慢!)。 LINQ无法帮助您,因为您的数据不可枚举。

答案 3 :(得分:0)

为了完整起见,这是一个LINQ解决方案(但它的性能较低,可读性低于Ginosaji的解决方案!)

public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }

    public static bool IsContained(Range super, Range sub)
    {
        return super.Min <= sub.Min
            && super.Max >= sub.Max;
    }
}

public class Itemi
{
    public Itemi()
    {
        properties = new Range[25];
        for (int i = 0; i < properties.Length; i++)
        {
            properties[i] = new Range();
        }
    }

    private Range[] properties;

    public IEnumerable<Range> Properties { get { return properties; } }

    public static bool IsContained(Itemi super, Itemi sub)
    {
        return super.properties
            .Zip(sub.properties, (first, second) => Tuple.Create(first, second))
            .All((entry) => Range.IsContained(entry.Item1, entry.Item2));
    }

    public Range Prop1 
    { 
        get { return properties[0]; }
        set { properties[0] = value; }
    }

    public Range Prop2
    {
        get { return properties[1]; }
        set { properties[1] = value; }
    }

    // ...
}