• 카테고리
    • 전체 글

    • 카테고리1
    • 카테고리2
    • 카테고리3
    • 카테고리4
  • 태그
  • 방명록

List<T> Generic 형 Find 함수 사용방법

기술자료/OS 2010. 7. 14. 11:32

.NET 2.0 부터 제공되는 Generic 형 Class. System.Collection.Generic 이라는 네임스페이스에 존재하는 내용이다. Collection에서는 모든 값들을 Object를 사용하기 때문에 매번 Casting 을 해야 했고, 그에 따른 성능상 문제로 인해 대안점 처럼 꺼내든 것이다. 뭐 Generic의 역사나 기타 방향성문제는 다른 문서들을 참고하시고..

여기서는 generic에 있는 각 형태에서 제공하는 find라는 함수를 이용하는 방법을 언급하려 한다. 물론 foreach와 같은 순환문을 이용해서 직접 find 함수를 구현할 수 있지만, 최소한 내부에 구현된 find 함수의 성능이 그나마 내가 직접 짠 것 보다는 좋을 것이라는 생각에 최대한 애용하는 편이다.

이 find 함수의 기본 형은 아래와 같다.

public T Find (
	Predicate<t> match
)

 

위의 형태에 대한 정의 내용을 보면 Predicate<T> 라는 게 있는데, 바로 이 부분에 대리자 역할을 하는 함수가 필요로 한다. match 라는 의미는 자신이 찾는 값의 형태인 경우에는 true 혹은 false를 돌려달라는 의미다.

여기서 개인적으로 가진 의문은 왜 find를 저렇게 구현했을까 했던 점이다. 만일 List<int> aaa 라는 개체를 만들었다면, aaa.find(1111) 식으로 aaa.find(<T>) 형태로 제공되었으면 그냥 썼을텐데, 저런식으로 만드니 원 접근이 될 터인가.. 했다. 하지만, 정작 <T> 안의 값의 형태가 복합형이고, 그 안에 찾는 조건이 복잡한 경우라면 오히려 위의 방법은 좋은 대안 식이라고나 할까?

 

일단 MSDN에서 제공되는 예제를 먼저 보자.

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>();

        dinosaurs.Add("Compsognathus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Oviraptor");
        dinosaurs.Add("Velociraptor");
        dinosaurs.Add("Deinonychus");
        dinosaurs.Add("Dilophosaurus");
        dinosaurs.Add("Gallimimus");
        dinosaurs.Add("Triceratops");

        Console.WriteLine("\nFind(EndsWithSaurus): {0}", 
            dinosaurs.Find(EndsWithSaurus));
    }

    // Search predicate returns true if a string ends in "saurus".
    private static bool EndsWithSaurus(String s)
    {
        if ((s.Length > 5) && 
            (s.Substring(s.Length - 6).ToLower() == "saurus"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

 

끝의 글자가 saurus 로 끝나는 명칭을 찾는 로직. 저기서 보면 Find 안에 특정 값이 들어간게 아니고, 특정 함수가 들어가 있다. 즉 값의 결과가 true/false로 떨어지는 독자적인 함수가 있으면 된다.  위의 예제는 바로 List에 담긴 내용들 중 맨 끝의 글자가 saurus가 들어 있는지 체크한 뒤 있으면 true, 없으면 false로 돌려준다.

대충 이해가 되려나 싶다.

그런데, 내가 걸린 문제는 이렇다. 위의 예제대로라면, 실제 find를 사용하는 것은 그 찾으려는 값이 밖에 있다는 사실. 만일 위의 예제대로 라면, 찾기 로직 안에 saurus 라는 값 처럼 아예 박혀 있어야 되는데, 실제로는 저 값이 외부에서 받는 값일때는 걸리게 된다.

예를 들어보자. 사용자가 검색하는 단어를 기준으로 찾는다고 하자.
입력되는 값에 따라 찾는 내용이 달라져야 되는데, 이 경우에는 위와 같은 방법을 사용하면 곤란해질 수 밖에 없다. 그렇다면?

위의 예제를 보면 함수를 넣기 위해 static private로 만들었는데, 그것을 delegate라는 대리자를 사용해서 원큐로 만드는 것이다. txtInput 이라는 Text 박스에서 입력값이 생겼을 때 찾기 명령을 실행 시키는 예제로직을 만들어보았다.

List<string> aryData = new List<string>();

public Test()
{
    aryData.Add("apple");
    aryData.Add("pineapple");
    aryData.Add("steel");
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    string sResult = aryData.Find(delegate(string s) {
        return s.Equals(txtInput.Text);
    });

    if(string.IsNullOrEmpty(sResult))
        MessageBox.Show(sResult);
}

 

대략적으로 보면 알겠지만,

Find 라는 함수 뒤에 delegate 라는 대리자를 선언하고, 그 안에 가상 함수로 들어오는 파라미터 값을 정의한다. string s 부분이 있는데, 그 부분이 바로 Find 에서 역으로 호출 될 때 들어오는 값이다. 만일 List<int> 라면 int 가 되어야 할 것이다.

그리고 최종적으로 돌려주는 값은 true, false로 나올 수 있는 값이면 된다.

그러면 실제적으로 Find의 Return 값은 찾은 값을 돌려주게 된다. 지금은 List<string> 이니 돌려주는 값은 당연히 string. 만일 int면 int가 될 것이다.

 

정리하며.

물론 사람이 만든 코드이기 때문에, 성능이 월등하리라 볼 수는 없다. 하지만, 최소한 그 분야의 대가들이며, 또 내부적인 구현 시, 순수 .NET으로 만들지 않고, 성능을 위해 억지로 Binary로 만들기도 한다. 즉 알지는 못하나, 최소한 날로 짜는 것 보다 더 나은 성능을 보여줄 수 있다는 것이다.

이런 내 함수들을 활용 방법이 의외 복잡하더라도 작정하고 사용하다 보면 지금 보다 더 나은 성능을 보장할 수 있다.

 

복합형 값용 List<T>.Find 사용방법 예제.

사람 정보 중 이름이 같은 데이터를 메시지 박스에 표현 하는 방법

class PersonData
{
    public PersonData(string sName, string sSocialNo)
    {
        _name = sName;
        _socialNo = sSocialNo;
    }

    string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    string _socialNo;
    public string SocialNo
    {
        get
        {
            return _socialNo;
        }
        set
        {
            _socialNo = value;
        }
    }

}

List<persondata> aryData = new List<persondata>();

public Test()
{
    aryData.Add(new PersonData("홍길동", "123444-444422"));
    aryData.Add(new PersonData("조조", "123444-444422"));
    aryData.Add(new PersonData("유비", "123444-444422"));
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    PersonData sResult = aryData.Find(delegate(PersonData p) {
        return p.Name.Equals(txtInput.Text);
    });

    if(sResult != null)
        MessageBox.Show(sResult.Name + sResult.SocialNo);
}
728x90
블로그 이미지

하인도1

[하인드/하인도/인도짱 의 홈페이지] 저만의 공간입니다. 다양한 소재들을 나열하는 아주 단순 무식한 홈페이지 입니다. 다양한 문서 자료도 있겠지만, 저의 푸념들도 있답니다.

250x250

블로그 내에 소스 코드 삽입 이사온 기념 스킨도... RSS 전문 기능 비활성화 관련. 스킨 바꾸어 보았습니다. 서버 파일 정리 좀 했습니다.

«   2025/06   »
일 월 화 수 목 금 토
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

지름신 Tutorial e-book Google Apps Engine 매뉴얼 좀 Visual Studio twi2me 개발환경 오류 협업 수 것 친구 비스킷 Buscuit MOSS 2007 java 블로그 불만 moss WSS me2photo Azure 인터파크 2010 SharePoint windows me2dayzm me2sms

  • Total :
  • Today :
  • Yesterday :

Copyright © 2015-2025 Socialdev. All Rights Reserved.

Copyright © 2015-2025 Socialdev. All Rights Reserved.

티스토리툴바