LINQ之First,FirstOrDefault

返回LINQ大全首頁

First()

First()基本用法相當於列表[0]

public static TSource First <TSource>(此IEnumerable <TSource>源);
MSDN

代碼示例:

public static class Program
{
    static void Main( string[] args )
    {
        int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
        int result  = numbers.First();

        System.Console.WriteLine( "數據:{0}", numbers.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }

    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 
數據:[1], [2], [3], [5], [7], [11],
結果:1

First()可以通過在參數中指定條件,獲取第一個滿足條件的元素。

public static TSource First<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate );

讓我們編寫一個從數組中獲取首個偶數的案例。

代碼示例:

public static class Program
{
    static void Main( string[] args )
    {
        int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };

        // 獲取偶數
        int result  = numbers.First( value => value % 2 == 0 );

        System.Console.WriteLine( "數據:{0}", numbers.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }

    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 

數據:[1][2][3][5][7][11],
結果:2

由於條件可以用lambda表達式編寫,因此可以快速編寫簡單的條件。

現在,讓我們編寫一個從數組中搜索並獲取具有指定名稱的案例。

代碼示例:

public static class Program
{
    private class Parameter
    {
        public int      ID      { get; set; }
        public string   Name    { get; set; }

        public override string ToString()
        {
            return string.Format( "ID:{0}, Name:{1}", ID, Name );
        }
    }

    static void Main( string[] args )
    {
        Parameter[] parameters = new Parameter[]
        {
            new Parameter() { ID =  5, Name = "正一郎" },
            new Parameter() { ID = 13, Name = "清次郎" },
            new Parameter() { ID = 25, Name = "誠三郎" },
            new Parameter() { ID = 42, Name = "徵史郎" },
        };

        // Name爲徵史郎
        Parameter result    = parameters.First( value => value.Name == "徵史郎" );

        System.Console.WriteLine( "數據:{0}", parameters.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }

    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 
數據:[ID5,名稱:Seiichiro][ID13,名稱:Seijiro][ID25,名稱:Seisaburo][ID42,名稱:Seishiro],
結果:ID:42名:徵史郎

使用First()有兩種情況會拋出異常,一種是序列爲空的時候,會報錯System.InvalidOperationException:序列不包含任何元素
另一種是沒有元素符合條件的時候,會報錯System.InvalidOperationException:該序列不包含匹配的元素

FirstOrDefault()

如果您不想四處寫try-catch的話,用FirstOrDefault()可以解決這個問題。
它的作用是,在上述異常的情況下,將返回該類型的默認值

public static TSource FirstOrDefault<TSource>( this IEnumerable<TSource> source );
public static TSource FirstOrDefault<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate );
MSDN

代碼示例:

public static class Program
{
    static void Main( string[] args )
    {
        int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };

        int result = 0;
        try
        {
            // 找比20大的值
            result = numbers.FirstOrDefault( value => value > 20 );
        }
        catch( System.Exception i_exception )
        {
            System.Console.WriteLine( "意外……:{0}", i_exception );

            System.Console.ReadKey();
            return;
        }        
        // 輸出
        System.Console.WriteLine( "數據:{0}", numbers.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }
    
    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 

數據:[1], [2], [3], [5], [7], [11],
結果:0

int型默認值爲0,所以返回0。
那麼序列是空的情況會怎麼樣呢?

代碼示例:

public static class Program
{
    static void Main( string[] args )
    {
        // 空數組
        int[] numbers = new int[] { };

        int result = 0;
        try
        {
            result = numbers.FirstOrDefault();
        }
        catch( System.Exception i_exception )
        {
            System.Console.WriteLine( "意外……:{0}", i_exception );

            System.Console.ReadKey();
            return;
        }        

        // 輸出
        System.Console.WriteLine( "數據:{0}", numbers.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }

    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 

數據:
結果:0

這種情況下也不例外,同樣是0
那麼自己製作的數據類的序列情況怎麼樣呢?

代碼示例:

public static class Program
{
    private class Parameter
    {
        public int      ID      { get; set; }
        public string   Name    { get; set; }

        public override string ToString()
        {
            return string.Format( "ID:{0}, Name:{1}", ID, Name );
        }
    }

    static void Main( string[] args )
    {
        Parameter[] parameters = new Parameter[]
        {
            new Parameter() { ID =  5, Name = "正一郎" },
            new Parameter() { ID = 13, Name = "清次郎" },
            new Parameter() { ID = 25, Name = "誠三郎" },
            new Parameter() { ID = 42, Name = "徵史郎" },
        };

        Parameter result = new Parameter();
        try
        {
            result = parameters.FirstOrDefault( value => value.ID == 30 );
        }
        catch( System.Exception i_exception )
        {
            System.Console.WriteLine( "例外だよ……:{0}", i_exception );

            System.Console.ReadKey();
            return;
        }        

        // 輸出
        System.Console.WriteLine( "數據:{0}", parameters.Text() );
        System.Console.WriteLine( "結果:{0}", result );

        System.Console.ReadKey();
    }

    public static string Text<TSource>( this IEnumerable<TSource> i_source )
    {
        string text = string.Empty;
        foreach( var value in i_source )
        {
            text += string.Format( "[{0}], ", value );
        }
        return text;
    }
} 

數據:[ID:5, Name:正一郎], [ID:13, Name:清次郎], [ID:25, Name:誠三郎], [ID:42,名稱:徵史郎] ,
結果:

class的預設值是null,所以結果是空的。

因爲FirstOrDefault()不會發生意外,所以很方便。只是有需要注意的地方。如果是class等數據類型的話,沒找到元素會返回空。

但是在數值型的情況下,替換值會變成某種總計的值,所以很難判斷是否沒有找到。在前面的示例中,如果找到偶數元素得到0,則不知道是找到了0元素還是沒有找到,所以返回了預設值0。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章