2013-07-21 2 views
6

함수를 100 번 오버로드하거나 다른 유형의 Compareer를 100 개 작성하는 대신 하나의 함수 내에서 유형을 확인하기로 결정했습니다.유형을 확인하는 가장 빠른 방법은 무엇입니까?

예를 들어, 기본 비교자를 사용하여 2 개의 객체 내에서 일련의 유형 (프리미티브 및 문자열) 값을 비교합니다. 여기

public class DefComparer : IComparer<object> { 
    public int Compare(object a, object b) { 
     .... // a = a.GetType().GetField(field).GetValue(a); - not important for the question but I'm just showing that a&b below are different references 
     switch (a.GetType().Name) { 
      case "Byte": 
       if ((byte)a == (byte)b) return 0; 
       else if ((byte)a > (byte)b) return 1; 
       else return -1; 
      case "UInt16": 
       if ((ushort)a == (ushort)b) return 0; 
       else if ((ushort)a > (ushort)b) return 1; 
       else return -1; 
      case "SByte": 
       if ((sbyte)a == (sbyte)b) return 0; 
       else if ((sbyte)a > (sbyte)b) return 1; 
       else return -1; 
      case "Int16": 
       ... 

내가 if/else 문 체인보다 빠른이라고하는 switch 문을 사용하고 있습니다 : 그것은 다음과 같은 코드가 포함되어 있습니다. 그러나 a.GetType().Name은 동적으로 얻은 문자열을 반환하며이 메서드에는 문자열 비교가 포함됩니다. 그것은 나에게 특히 빠르다고 들리지 않는다. Comparer은 많은 양의 데이터에 사용되기 때문에 기술적으로 가능한 한 빨리 수행해야합니다.

Q : 문자열 비교를 포함하지 않는 개체 유형을 빠르게 검사 할 수있는 방법이 있습니까? 가능한 가장 빠른 방법은 무엇입니까?

+1

당신은'Comparer.Default'를 찾고 있습니다. – SLaks

+0

또는 ((IComparable) a) .CompareTo (b)를 호출하십시오. – usr

+0

아니요. 'Comparer.Default'가 필요하지 않습니다. 내 게시물을 더 명확하게 편집했습니다. 제 질문은 유형을 확인하는 빠른 방법에 관한 것입니다. – brandon

답변

6

당신 손에 가지고 있습니다. 사용 TypeCode

 int a = 10; 
     Type t = a.GetType(); 

     switch (Type.GetTypeCode(t)) 
     { 
      case TypeCode.Boolean: 
       break; 
      case TypeCode.Byte: 
       break; 
      case TypeCode.Char: 
       break; 
      case TypeCode.DBNull: 
       break; 
      case TypeCode.DateTime: 
       break; 
      case TypeCode.Decimal: 
       break; 
      case TypeCode.Double: 
       break; 
      case TypeCode.Empty: 
       break; 
      case TypeCode.Int16: 
       break; 
      case TypeCode.Int32: 
       break; 
      case TypeCode.Int64: 
       break; 
      case TypeCode.Object: 
       break; 
      case TypeCode.SByte: 
       break; 
      case TypeCode.Single: 
       break; 
      case TypeCode.String: 
       break; 
      case TypeCode.UInt16: 
       break; 
      case TypeCode.UInt32: 
       break; 
      case TypeCode.UInt64: 
       break; 
      default: 
       break; 
     } 

이것은 모든 프리미티브를 지원합니다. 사용자 정의 객체 용 else if 문을 TypeCode.Object 안에 작성하십시오.

이 정보가 도움이되기를 바랍니다.

+0

예, 검사 방법이 빠릅니다. 'TypeCode' 열거 형에 대해 알지 못했습니다. – brandon

+0

@brandon이 환호했다. 이제 너는 그것에 대해 알고있다. –

+0

@brandon 적절한 유형으로 변환하고 로컬 변수에 저장 한 다음 'Unboxing'대신에 성능을 두 번 비교하는 것이 좋습니다 –

3

다양한 주석을 사용하여 다양한 유형의 하위 객체가있는 구조화 된 데이터가있는 것처럼 보입니다.

컬렉션이 큰 경우 가장 빠른 방법은 관심있는 모든 필드/속성을 강력한 형식으로 끌어와 강력한 형식의 비교를 수행하는 단일 메서드를 만드는 동적 코드gen (아마도 식 트리 포함)이 될 것입니다.

기본적으로 리플렉션을 사용하여 컬렉션 멤버 유형에서 필드/속성 유형을 동적으로 가져옵니다. 그런 다음 표현식을 작성하고이를 Expression.Equal으로 전달하고 모든 결과를 Expression.AndAlso으로 전달하십시오. 표현식을 컴파일하면 컬렉션에 포함 된 특정 유형의 객체 두 개를 사용하는 대리인이 생깁니다.

시작 시간은 질문에서 보여준 코드보다 몇 배 느릴 수 있지만 개체 당 비용은 훨씬 낮습니다. 손익분기 점이 어디 있는지 테스트 해봐야하지만, 아마도 수천 명에 불과할 것입니다.

관련 문제