LINQ之Contains

返回LINQ大全首頁

Contains()

Contains()可以用來判斷序列中是否存在指定的元素。
MSDN
public static bool Contains<TSource>( this IEnumerable<TSource> source, TSource value );
但是要注意此行爲會根據元素是值類型還是引用類型而略有變化。

代碼示例:

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

        bool reaultA = numbers.Contains( 8 );
        bool reaultB = numbers.Contains( 3 );
        bool reaultC = numbers.Contains( 12 );

        System.Console.WriteLine( "numbers:{0}", numbers.Text() );
        System.Console.WriteLine( " 包含8:{0}", reaultA );
        System.Console.WriteLine( " 包含3:{0}", reaultB );
        System.Console.WriteLine( "包含12:{0}", reaultC );

        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;
    }
}

numbers:[0], [1], [2], [3], [4], [5], [6], [7], [8], [9],
包含8:True
包含3:True
包含12:False

接下來讓我們嘗試下引用類型。

代碼示例:

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 )
    {
        List<Parameter> parameters  = new List<Parameter>();

        Parameter valueA    = new Parameter() { ID = 0, Name = "正一郎" };
        Parameter valueB    = new Parameter() { ID = 5, Name = "清次郎" };
        Parameter valueC    = new Parameter() { ID = 3, Name = "誠三郎" };
        Parameter valueD    = new Parameter() { ID = 9, Name = "徵史郎" };

        parameters.Add( valueA );
        parameters.Add( valueB );
        parameters.Add( valueC );

        bool reaultA = parameters.Contains( valueA );
        bool reaultB = parameters.Contains( valueC );
        bool reaultC = parameters.Contains( valueD );

        System.Console.WriteLine( "parameters:{0}", parameters.Text() );
        System.Console.WriteLine( "包含正一郎:{0}", reaultA );
        System.Console.WriteLine( "包含誠三郎:{0}", reaultB );
        System.Console.WriteLine( "包含徵史郎:{0}", reaultC );

        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;
    }
}

parameters:[ID:0, Name:正一郎], [ID:5, Name:清次郎], [ID:3, Name:誠三郎],
包含正一郎:True
包含誠三郎:True
包含徵史郎:False

一切正常。
現在讓我們稍微改變一下方法。
下面創建兩個內容相同引用不同的類,結果如何呢?

代碼示例:

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 )
    {
        List<Parameter> parameters  = new List<Parameter>();

        // 內容相同,引用不同
        Parameter valueA    = new Parameter() { ID = 0, Name = "徵史郎" };
        Parameter valueB    = new Parameter() { ID = 0, Name = "徵史郎" };
        parameters.Add( valueA );

        bool reaultA = parameters.Contains( valueA );
        bool reaultB = parameters.Contains( valueB );

        System.Console.WriteLine( "parameters:{0}", parameters.Text() );
        System.Console.WriteLine( "相同引用:{0}", reaultA );
        System.Console.WriteLine( "不同引用:{0}", reaultB );

        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;
    }
}

parameters:[ID:0, Name:徵史郎],
相同引用:True
不同引用:False

雖然valueAvalueB內容相同,但是由於引用不同,所以Contains()將其判斷爲不同的元素。
那麼,即使它是引用類型,如果我要根據內容屬性是否相同來檢查元素的存在,該怎麼辦?

Contains()具有重載功能。
您可以獨立指定比較方法。用於比較的數據必須繼承IEqualityComparer接口。
MSDN
public static bool Contains<TSource>( this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer );
IEqualityComparer
代碼示例:

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 );
        }
    }

    // 繼承IEqualityComparer
    private class ParameterComparer : IEqualityComparer<Parameter>
    {
    	// 比較方法
        public bool Equals( Parameter i_lhs, Parameter i_rhs )
        {
            if( i_lhs.ID == i_rhs.ID &&
                i_lhs.Name == i_rhs.Name )
            {
                return true;
            }
            return false;
        }
        public int GetHashCode( Parameter i_obj )
        {
            return i_obj.ID ^ i_obj.Name.GetHashCode();
        }
    }

    static void Main( string[] args )
    {
        List<Parameter> parameters  = new List<Parameter>();

        // 內容相同
        Parameter valueA    = new Parameter() { ID = 0, Name = "徵史郎" };
        Parameter valueB    = new Parameter() { ID = 0, Name = "徵史郎" };
        parameters.Add( valueA );

        ParameterComparer comparer  = new ParameterComparer();
        bool reaultA = parameters.Contains( valueA, comparer );
        bool reaultB = parameters.Contains( valueB, comparer );

        System.Console.WriteLine( "parameters:{0}", parameters.Text() );
        System.Console.WriteLine( "相同引用:{0}", reaultA );
        System.Console.WriteLine( "不同引用:{0}", reaultB );

        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;
    }
}
parameters:[ID:0, Name:徵史郎],
相同引用:True
不同引用:True

現在兩個結果都爲true了。

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