查找类中的所有属性是否相同

本文关键字:属性 是否 查找 | 更新日期: 2023-09-27 18:27:13

我有一个简单的类,它包含4个类似的双重属性

 public MyClass
 {
     public MyClass(double all = 0)
     {
         Top = Bottom = Left = Right = all;
     }
     public MyClass(double lr = 0, double tb = 0)
     {
         Top = Bottom = tb;
         Left = Right = lr;
     }
     public MyClass(double l = 0, double r = 0, double t = 0, double b = 0)
     {
         Top = t;Bottom = b;Left = l;Right = r;
     }
     public double Top {get; private set;}
     public double Bottom {get; private set;}
     public double Left {get; private set;}
     public double Right {get; private set;}
}

有没有一种简单的方法可以检查所有属性是否具有相同的值?我宁愿不使用if (Top == Bottom) && (Top == Left) ...,因为它有点乱IMHO。可以在LINQ中完成吗?

查找类中的所有属性是否相同

LINQ处理集合。你没有集合,你有四个独立的属性。

你要做的任何事情都会迫使它进入LINQ,只会让它变得更加混乱。

只需使用普通的旧C#:

public bool AllPositionsEqual
{
    get
    {
        return Top == Bottom 
            && Left == Right
            && Left == Top;
    }
}

这一点现在你很清楚,当另一位读者读到它时,你也很清楚,几个月后你读到它。

如果您将属性填充到集合中,只是为了能够对其调用LINQ方法以确定它们都是相同的,那么就违反了"最小惊讶原则"。该代码的读取器将转到"WTF"。

相反,如果你想在任意类上做到这一点(这也是一个非常令人困惑的要求),你可以这样做:

  • 使用反射获取所有属性
  • 获取集合中此实例的所有属性值
  • 在此集合上,调用Distinct()

然后您将拥有一个合法的LINQ用例。现在,你还没有。

您可以将它们插入HashSet<double>:

var doubles = new HashSet<double> { Top, Left, Right, Bottom };
if (doubles.Count == 1)
{
    // Do stuff
}

或者使用Enumerable.Distinct:

var doubles = new[] { Top, Bottom, Left, Right };
if (doubles.Distinct().Count() == 1)
{
    // Do stuff
}

但也许最简单的方法是创建一个方法(或者一个属性,如果你喜欢的话):

public class MyClass
{
    public bool AreAllPropertiesSame()
    {
        return Top == Bottom && Left == Top && Right == Left;
    }
}

请注意,任何LINQ的使用都会比对4个属性进行简单的if检查产生更多的开销。我肯定会选择一种简单明了的属性或方法。不要因为可以而听从LINQ,使用它是因为它是工作的最佳工具,而这里显然不是。

为了强调@CodeCaster已经提到的关于消息的内容,以下是合适的代码:

var properties = typeof(MyClass).GetProperties();
var first = proerties[0].GetValue(myInstance, null);
if (properties.Select(x => x.GetValue(myInstance, null)).All(x => x.Equals(first)) 
{ 
    /* ... */ 
}

这将通过反射检查类型MyClass中的所有属性。然而,一切都比这种方法好,只是为了完整性才添加它。如果你想让它稳定,你至少还必须证明这个类是否真的有任何属性。

这仅适用于未编制索引的属性。如果你的财产被索引了,你还必须证明每一个元素都会变得更脏。

现在将其与@Yuval的Top == Bottom && Left == Top && Right == Left进行比较。

我非常喜欢为这样的情况编写一个方法,因为它是可重用的,并且有一个可以告诉这里发生了什么的名称。

public static bool AllEqual<T>(T frist, params T[] values)
{
    return values.All(v => Equal(first,v));
}

然后像这样使用:

ObjectHelper.AllEqual(Top, Bottom, Left, Right);
bool b = (Top == (new double[] { Top, Bottom, Left, Right }).Average());

这可能是另一种变通方法?

Dom