C# Difference between First() and Find()

前端 未结 5 1454
花落未央
花落未央 2020-12-08 19:08

So I know that Find() is only a List method, whereas First() is an extension for any IEnumerable. I als

相关标签:
5条回答
  • 2020-12-08 19:14

    First will throw an exception when it finds nothing, FirstOrDefault however does exactly the same as Find (apart from how it iterates through the elements).

    0 讨论(0)
  • 2020-12-08 19:16

    1- Find() returns Null if the entity is not in the context but First() will throw an exception
    2- Find() returns entities that have been added to the context but have not yet been saved to the database

    0 讨论(0)
  • 2020-12-08 19:32

    BTW Find is rather equal to FirstOrDefault() than to First(). Because if predicate of First() is not satisfied with any list elements you will get an exception. Here what returns a dotpeek, another great free reflector replacement with some of ReSharper features

    Here for Enumerable.First(...) and Enumerable.FirstOrDefault(...) extension methods:

        public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            foreach (TSource element in source) { 
                if (predicate(element)) return element;
            } 
            return default(TSource); 
        }
    
    
        public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            foreach (TSource element in source) {
                if (predicate(element)) return element; 
            }
            throw Error.NoMatch();
        }
    

    and here is for List<>.Find:

    /// <summary>
    /// Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire <see cref="T:System.Collections.Generic.List`1"/>.
    /// </summary>
    /// 
    /// <returns>
    /// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type <paramref name="T"/>.
    /// </returns>
    /// <param name="match">The <see cref="T:System.Predicate`1"/> delegate that defines the conditions of the element to search for.</param><exception cref="T:System.ArgumentNullException"><paramref name="match"/> is null.</exception>
    [__DynamicallyInvokable]
    public T Find(Predicate<T> match)
    {
      if (match == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
      for (int index = 0; index < this._size; ++index)
      {
        if (match(this._items[index]))
          return this._items[index];
      }
      return default (T);
    }
    
    0 讨论(0)
  • 2020-12-08 19:33

    Here's the code for List<T>.Find (from Reflector):

    public T Find(Predicate<T> match)
    {
        if (match == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
        }
        for (int i = 0; i < this._size; i++)
        {
            if (match(this._items[i]))
            {
                return this._items[i];
            }
        }
        return default(T);
    }
    

    And here's Enumerable.First:

    public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        if (predicate == null)
        {
            throw Error.ArgumentNull("predicate");
        }
        foreach (TSource local in source)
        {
            if (predicate(local))
            {
                return local;
            }
        }
        throw Error.NoMatch();
    }
    

    So both methods work roughly the same way: they iterate all items until they find one that matches the predicate. The only noticeable difference is that Find uses a for loop because it already knows the number of elements, and First uses a foreach loop because it doesn't know it.

    0 讨论(0)
  • 2020-12-08 19:36

    Since List<> is not indexed in any way, it has to go through all values to find a specific value. Therefore it doesn't make much of a difference compared to traversing the list via an enumerable (apart from the creation of a enumerable helper object instance).

    That said, keep in mind that the Find function was created way earlier than the First extension method (Framework V2.0 vs. V3.5), and I doubt that they would have implemented Find if the List<> class had been implemented at the same time as the extension methods.

    0 讨论(0)
提交回复
热议问题