63

What is the best way to get a value from a ICollection? We know the Collection is empty apart from that.

RBT
  • 24,161
  • 21
  • 159
  • 240

5 Answers5

95

You can use LINQ for this:.

var foo = myICollection.OfType<YourType>().FirstOrDefault();
// or use a query
var bar = (from x in myICollection.OfType<YourType>() where x.SomeProperty == someValue select x)
   .FirstOrDefault();
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
  • 2
    FirstOrDefault is defined on ICollection or IEnumerable (non-generic)? Where? What would work though: myICollection.OfType().FirstOrDefault(); – Christoph Rüegg Dec 12 '08 at 17:42
  • 3
    This is the right answer. First and FirstOrDefault even use that IList optimisation internally where possible. – Daniel Earwicker Dec 12 '08 at 23:46
  • I was looking the FirstOrDefault() but intellisense was telling me that no way... until i added the using for System.Linq. So before doing any of this, check you added at the beginning of your code: `using System.Linq;` – Juan Ignacio Avendaño Huergo Oct 11 '21 at 14:15
26

The simplest way to do this is:

foreach(object o in collection) {
  return o;
}

But this isn't particularly efficient if it's actually a generic collection because IEnumerator implements IDisposable, so the compiler has to put in a try/finally, with a Dispose() call in the finally block.

If it's a non-generic collection, or you know the generic collection implements nothing in its Dispose() method, then the following can be used:

IEnumerator en = collection.GetEnumerator();
en.MoveNext();
return en.Current;

If you know if may implement IList, you can do this:

IList iList = collection as IList;
if (iList != null) {
  // Implements IList, so can use indexer
  return iList[0];
}
// Use the slower way
foreach (object o in collection) {
  return o;
}

Likewise, if it's likely it'll be of a certain type of your own definition that has some kind of indexed access, you can use the same technique.

Chris
  • 1,685
  • 10
  • 15
8
collection.ToArray()[i]

This way is slow, but very simple to use.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
mehrdad seyrafi
  • 3,084
  • 2
  • 19
  • 16
  • 5
    This copies the entire collection just to get one value. – Matt Feb 10 '14 at 22:38
  • 2
    "We know the Collection is empty apart from that.". For the sake of simplicity, the above would have its uses. Although not the best generic answer as it would be abused. – Skarsnik Mar 08 '16 at 00:30
5

Without generics and because ICollection implements IEnumerable you can do like in example 1. With generics you simple need to do like example 2:

List<string> l = new List<string>();
l.Add("astring");

ICollection col1 = (ICollection)l;
ICollection<string> col2 = (ICollection<string>)l;

//example 1
IEnumerator e1 = col1.GetEnumerator();
if (e1.MoveNext())
    Console.WriteLine(e1.Current);

//example 2
if (col2.Count != 0)
    Console.WriteLine(col2.Single());
bruno conde
  • 47,767
  • 15
  • 98
  • 117
  • 2
    example 2 isn't right because ICollection doesn't implement method Single(). –  Dec 12 '08 at 17:18
  • This is a Linq extension method. Take a look at msdn doc : http://msdn.microsoft.com/en-us/library/y2fx0ty0.aspx – bruno conde Dec 12 '08 at 17:26
0

If you know your collection has only one item, should only ever have one item, you can use the Linq extension method Single().

This converts a ICollection<T> into a T object containing the single item of that collection. If the length of the collection is 0, or more than one, this will throw an InvalidOperationException.

JAD
  • 2,035
  • 4
  • 21
  • 35