2

This question is quite similar to this C# question, but rather than them all being equal to a particular known value, I want to know if they are all the same as each other no matter what that value is.

My list contains numerous objects such as:

public MyClass {
    public int Id { get; set; }
    public string MyProperty { get; set;}
}

My initial approach was:

List<MyClass> MyList = new List<MyClass>();
//... Add some values

string firstResult = MyList.First().MyProperty;
return MyList.All(x => x.MyProperty.Equals(firstResult))

But I feel there is a more elegant way to do this?

Harry Adams
  • 423
  • 5
  • 16
  • I find it quite elegant! – Gian Paolo May 20 '22 at 15:32
  • 3
    That seems fine. You could do GroupBy and count the resulting groups, which might be overkill, or a basic foreach loop. "Elegant" isn't something we can really help with. – gunr2171 May 20 '22 at 15:32
  • Another option would be `DistinctBy`: `MyList.DistinctBy(x => x.MyProperty).Count() == 1` – Kirk Woll May 20 '22 at 15:37
  • Not sure how to phrase the question: Do you get a filled list _and then_ you need to check this? Or could you just track the property of each newly added entry, on adding? That shifts the "burden" to the add, but may spare you from iterating the whole list? – Fildor May 20 '22 at 15:37
  • Maybe I'm wrong, but I think a LINQ (or other) method such the one you are looking for does not exist. Have a look at [this article](https://ericlippert.com/2009/05/18/foreach-vs-foreach/) from Eric Lippert, former c# designer; No need to create such particular method when your two liner get the same result. Just my 2 cents – Gian Paolo May 20 '22 at 15:38

1 Answers1

4

What you have is fine. It's essentially equivalent to:

var firstResult = MyList[0].MyProperty;
bool allSame = true;
foreach (var entry in MyList)
{
    if (!entry.MyProperty.Equals(firstResult)
    {
        allSame = false;
        break;
    }
}

...just with much less code.

In order to test that they all have the same value you need to know what one of the object's value is, which is why you'll always need to get the "first" value and use that as the comparison (though, obviously, it doesn't matter if it's the first, last, middle, etc, as long as it's an index that exists).

Depending on your need, you could use either GroupBy or DistinctBy. When you're dealing with Lists this is less of a concern, but if you're using regular IEnumerables it means you need to compute the source multiple times.

var countOfMyProperties = MyList.GroupBy(x => x.MyProperty).Count();
// 1 = all the same
// >1 = not all the same

Using GroupBy allows you to ask the natural follow-up question "well, if not all of my objects have the same MyProperty value, how many distinct values are there (a "group"), and how many objects are in each group?"

Also, I'd recommend using x.MyProperty == firstResult rather than x.MyProperty.Equals(firstResult), if possible.

gunr2171
  • 16,104
  • 25
  • 61
  • 88
  • Thanks for the detailed answer. I thought LINQ would have some sort of built-in system, but I guess not! – Harry Adams May 20 '22 at 15:40
  • 1
    Why use == rather than .Equals()? I was always taught to use .Equals for strings, but this could of course be out of date – Harry Adams May 20 '22 at 15:41
  • Additionally thanks for your extra note on IEnumerables, it's a factor I had not considered – Harry Adams May 20 '22 at 15:42
  • I think you have a Java background. `==` and `.Equals()` are the same thing (mostly) in C#, and most people use `==` as the default for all comparison operations unless they specifically need something else. – gunr2171 May 20 '22 at 15:43
  • Haha. I did indeed start with Java in university, now work with C# day to day. Guess it just stuck in my mind erroneously. – Harry Adams May 20 '22 at 15:44
  • See https://stackoverflow.com/questions/1659097/why-would-you-use-string-equals-over – gunr2171 May 20 '22 at 15:48