LINQ之Contains

返回LINQ大全首页

Contains()

Contains()可以用来判断序列中是否存在指定的元素。
MSDN
public static bool Contains( this IEnumerable 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( this IEnumerable source, TSource value, IEqualityComparer 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了。

你可能感兴趣的:(C#,c#,.net,microsoft,linq,unity)