C#/LINQ

[C#]LINQ 특정 값 포함 여부 - Contains 메서드

DevStory 2022. 7. 18.

Contains 메서드

LINQ의 Contains() 메서드는 시퀀스 또는 컬렉션에 특정 요소가 포함되어 있는지 여부를 확인하기 위해 사용됩니다. 특정 요소가 존재하는 경우 true를 반환하고 그렇지 않으면 false를 반환합니다.

 

Contains() 메서드는 System.Linq 및 System.Collections.Generic 네임스페이스에 존재하며 이 둘은 네임스페이스가 다르므로 .Net Framework에서 제공하는 Contains() 메서드는 두 가지입니다.

 

먼저, System.Linq 네임스페이스에 존재하는 Contains() 메서드는 bool 타입의 값을 반환하며 두 가지 오버로드된 버전이 존재합니다. 두 가지 버전의 차이점은 IEqualityComparer 사용 여부입니다.

public static bool Contains<TSource>(
  this IQueryable<TSource> source, 
  TSource item);

public static bool Contains<TSource>(
  this IQueryable<TSource> source, 
  TSource item, 
  IEqualityComparer<TSource> comparer);

System.Collections.Generic 네임스페이스에 존재하는 Contains() 메서드도 bool 타입의 값을 반환합니다.

public bool Contains(T item);

참고로 사용자 정의 클래스 타입에서 특정 프로퍼티에 특정 값이 존재하는지 확인하기 위해서는 System.Linq의 Contains() 메서드를 사용해야 합니다.


예제 1. int 타입의 List

다음 예제는 int 타입의 List에서 30이 존재하는지 Contains() 메서드를 사용하는 예제입니다.

class Program
{
  static void Main(string[] args)
  {
    List<int> intList = new List<int>()
    {
      5, 10, 15, 20, 25, 30 
    };

    // 1. 질의 구문(Query Syntax)
    bool linqQueryResult = (from   num in intList
                            select num).Contains(30);

    // 2. 메서드 구문(Method Syntax)
    bool linqMethodResult1 = intList.Contains<int>(30);
    bool linqMethodResult2 = intList.AsEnumerable().Contains(30);
    bool linqMethodResult3 = intList.AsQueryable().Contains(30);

    Console.WriteLine("질의 구문 결과: " + linqQueryResult);
    Console.WriteLine("메서드 구문 결과: " + linqMethodResult1);
  }
}

[실행 결과]

질의 구문 결과: True
메서드 구문 결과: True

List 객체에서 Contains() 메서드를 호출하면 System.Collections.Generic 네임스페이스의 Contains() 메서드로 인식합니다. System.Linq의 Contains() 메서드를 호출하기 위해서는 다음 세 가지 방법 중 한 가지 방법을 사용하면 됩니다.

1. Contains() 메서드에 타입을 명시합니다.

2. AsEnumerable() 메서드로 IEnumerable 타입으로 변환합니다.

3. AsQueryable() 메서드로 IQueryable 타입으로 변환합니다.


예제 2. string 타입의 List

다음 예제는 string 타입의 List에서 문자열 "javascript"가 존재하는지 Contains() 메서드를 사용합니다.

class Program
{
  static void Main(string[] args)
  {
    List<string> strList = new List<string>()
    {
      "oracle", "Java", "JavaScript"
    };

    // 1. 질의 구문(Query Syntax)
    bool linqQueryResult = (from   num in strList
                            select num).Contains("javascript");

    // 2. 메서드 구문(Method Syntax)
    bool linqMethodResult = strList.Contains<string>("javascript");

    Console.WriteLine("질의 구문 결과: " + linqQueryResult);
    Console.WriteLine("메서드 구문 결과: " + linqMethodResult);
  }
}

[실행 결과]

질의 구문 결과: False
메서드 구문 결과: False

Linq의 기본 비교자는 문자열을 비교할 때 대소문자를 구분합니다. 대소문자 구분 없이 비교하기 위해서는 IEqualityComparer를 매개변수로 사용하는 Contains() 메서드를 사용합니다.

 

다음 예제는 대소문자 구분 없이 문자열 "javascript"가 존재하는지 확인합니다.

class Program
{
  static void Main(string[] args)
  {
    List<string> strList = new List<string>()
    {
      "oracle", "Java", "JavaScript"
    };

    // 1. 질의 구문(Query Syntax)
    bool linqQueryResult = (from   num in strList
                            select num)
                            .Contains("javascript", StringComparer.OrdinalIgnoreCase);

    // 2. 메서드 구문(Method Syntax)
    bool linqMethodResult = strList
        .Contains<string>("javascript", StringComparer.OrdinalIgnoreCase);

    Console.WriteLine("질의 구문 결과: " + linqQueryResult);
    Console.WriteLine("메서드 구문 결과: " + linqMethodResult);
  }
}

[실행 결과]

질의 구문 결과: true
메서드 구문 결과: true

예제 3. 사용자 정의 클래스

다음 예제는 사용자 정의 클래스인 Person 타입인 List에서 Person 클래스의 인스턴스가 존재하는지 Contains() 메서드를 사용합니다.

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
  public override string ToString()
  {
    return "Name: " + Name + ", Age: " + Age;
  }
}

class Program
{
  static void Main(string[] args)
  {
    List<Person> personA = new List<Person>
    {
      new Person{Name ="Bob", Age = 20},
      new Person{Name ="Nick", Age = 30},
      new Person{Name ="Tom", Age = 40}
    };

    List<Person> personB = new List<Person>
    {
        new Person{Name ="Bob", Age = 20}
    };
    
    // 1. 질의 구문(Query Syntax)
    bool linqQueryResult = (from   person in personA
                            select person).Contains(personB[0]);

    // 2. 메서드 구문(Method Syntax)
    bool linqMethodResult = personA.Contains<Person>(personB[0]);

    Console.WriteLine("질의 구문 결과: " + linqQueryResult);
    Console.WriteLine("메서드 구문 결과: " + linqMethodResult);
  }
}

[실행 결과]

질의 구문 결과: False
메서드 구문 결과: False

Contains() 메서드는 사용자 정의 클래스 타입의 인스턴스 값이 아닌 객체 참조를 확인합니다. 따라서, Contains() 메서드는 프로퍼티의 값이 동일한 인스턴스가 존재하더라도 false를 반환합니다.

 

위 문제를 해결하기 위해서는 IEqualityComparer 인터페이스를 구현해야 합니다.


예제 4. IEqualityComparer 구현

다음 예제는 IEqualityComparer 구현 클래스의 인스턴스를 Contains() 메서드의 두 번째 매개변수로 전달합니다.

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
  public override string ToString()
  {
    return "Name: " + Name + ", Age: " + Age;
  }
}

public class PersonComparer : IEqualityComparer<Person>
  {
  public bool Equals(Person x, Person y)
  {
    if (object.ReferenceEquals(x, y))
    {
        return true;
    }
    if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
    {
        return false;
    }
    return x.Name == y.Name && x.Age == y.Age;
  }

  public int GetHashCode(Person obj)
  {
    if (obj == null)
    {
        return 0;
    }
    int NameHashCode = obj.Name == null ? 0 : obj.Name.GetHashCode();
    int AgeHashCode = obj.Age.GetHashCode();
    return NameHashCode ^ AgeHashCode;
  }
}

class Program
{
  static void Main(string[] args)
  {
    List<Person> personA = new List<Person>
    {
      new Person{Name ="Bob", Age = 20},
      new Person{Name ="Nick", Age = 30},
      new Person{Name ="Tom", Age = 40}
    };

    List<Person> personB = new List<Person>
    {
      new Person{Name ="Bob", Age = 20}
    };

    PersonComparer personComparer = new PersonComparer();

    // 1. 질의 구문(Query Syntax)
    bool linqQueryResult = (from   person in personA
                            select person).Contains(personB[0], personComparer);

    // 2. 메서드 구문(Method Syntax)
    bool linqMethodResult = personA.Contains<Person>(personB[0], personComparer);

    Console.WriteLine("질의 구문 결과: " + linqQueryResult);
    Console.WriteLine("메서드 구문 결과: " + linqMethodResult);
  }
}

[실행 결과]

질의 구문 결과: True
메서드 구문 결과: True
반응형

댓글