2014-07-09 1 views
0

저는 공장을 사용하여 IComparer<User> 개체를 만들어 사용자 목록을 정렬하고 있습니다.불필요한 인터페이스 캐스트?

두 클래스가 있습니다. AscendingDescending 모두 IComparer<User>입니다. 여기에 코드입니다 :

namespace Test 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      List<User> users = new List<User>(); 
      users.Add(new User("foo", "bar")); 
      // ... 
      IComparer<User> cmp = ComparerFactory.GetComparer("FirstName", true); 
      if (cmp != null) 
      { 
       users.Sort(cmp); 
      } 
     } 
    } 

    public class User 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 

     public User(string firstName, string lastName) 
     { 
      FirstName = firstName; 
      LastName = lastName; 
     } 
    } 

    public class UserFirstNameComparer 
    { 
     public class Ascending : IComparer<User> 
     { 
      public int Compare(User u1, User u2) 
      { 
       return String.Compare(u1.FirstName, u2.FirstName, true); 
      } 
     } 

     public class Descending : IComparer<User> 
     { 
      public int Compare(User u1, User u2) 
      { 
       return new UserFirstNameComparer.Ascending().Compare(u1, u2) * -1; 
      } 
     } 
    } 

    public static class ComparerFactory 
    { 
     public static IComparer<User> GetComparer(string fieldName, bool ascending) 
     { 
      switch (fieldName) 
      { 
       case "FirstName": 
        return ascending ? 
         new UserFirstNameComparer.Ascending() : // ERROR IS HERE 
         new UserFirstNameComparer.Descending(); 
       //... 
      } 
      return null; 
     } 
    } 

는하지만 오류 (라인 : new UserFirstNameComparer.Ascending() :) : 얻을 그래서 문제가 무엇, 모두 IComparer 개체입니다, 나는 그것이 무엇을 의미하는지 이해 해달라고

Type of conditional expression cannot be determined because there is no implicit conversion between 'Test.UserFirstNameComparer.Ascending' and 'Test.UserFirstNameComparer.Descending'

를? 이상한 것은 내가 (? 불필요) 캐스트 오류를 ​​수정할 수 있다는 것입니다 : 나는 두 경우 모두에 캐스팅 할 때 물론

// This works 
return ascending ? 
    (IComparer<User>) new UserFirstNameComparer.Ascending() : 
    new UserFirstNameComparer.Descending(); 


// This works too 
return ascending ? 
    new UserFirstNameComparer.Ascending() : 
    (IComparer<User>) new UserFirstNameComparer.Descending(); 

가 작동합니다. 그러나 나는 그것이 왜 오직 하나의 형형색색으로 작동하는지, 왜 형형색색이 없는지는 왜 이해하지 못합니다. 어떤 아이디어?

(내가 VS 2012 사용하고, .NET의 v4.0.30319는)

+1

이 질문에 대한 답변보기 : http://stackoverflow.com/questions/202271/why-is-this-code-invalid-in-c –

+0

두 개의 'Comparers'(매우 어리석은 것) 대신에, 왜 당신은 그냥 하나의 일반'Comparer' (오름차순)를 만들고 list.Sort (cmp) .Reverse() 또는 list.OrderBy (cmp)/list.OrderByDescending (cmp) 할합니까? – Davio

+1

위와 같이'-1'을 곱하면'Compare' 호출의 결과 값이'-2147483648'이면 원하는대로 동작하지 않습니다. 일부 'Compare'구현은'-1','0' 및'+ 1' 이외의 다른 값을 반환하며 그렇게 할 수 있습니다. –

답변

3

cond ? X : Y 

그냥 필요 표현 중 하나 X의 컴파일 시간 형은 그 반대의 경우도 마찬가지 Y, 또는 컴파일시 형식으로 암시 적으로 변환입니다 (간체). 두 가지 유형의 모든 인터페이스와 기본 클래스를 검색하여 일부 "공통"유형을 찾으려고하지는 않습니다. (그렇다하더라도 공용 인터페이스가 여러 개인 경우 어떻게 처리 할 수 ​​있습니까?)

언어가 디자인 된 방식입니다. ?: 표현식을 해결할 때 고려할 수없는 메서드의 반환 형식과 관련이 없습니다.

솔루션을 이미 찾았으므로 X 및/또는 Y을 명시 적으로 원하는 유형으로 캐스팅하십시오.


은 두 개의 클래스 AscendingDescending를 작성하지 않고 또한 당신이 할 수있는 방법에 대한 제안이, 당신의 질문에 대답 가졌어요.당신은이 같은 IComparer<>을 만들 수 있습니다
return ascending ? 
    Comparer<User>.Create((u1, u2) => String.Compare(u1.FirstName, u2.FirstName, true)) 
    Comparer<User>.Create((u1, u2) => String.Compare(u2.FirstName, u1.FirstName, true)) 
    ; 

그래서 당신의 두 클래스에 대한 필요가 없습니다 (아마도).

+0

설명과 제안에 감사드립니다. 그것은 위대한 작품! –

+1

[Comparer <>. Create' 메서드] (http://msdn.microsoft.com/en-us/library/hh737198.aspx)는 .NET 4.5 (2012)에서 새로 추가되었습니다. 'Comparison <>'형식의 대리자는 .NET 2.0 (2005) 이후에 존재했습니다. –

3

new UserFirstNameComparer.Ascending()Ascending의 인스턴스를 반환합니다. new UserFirstNameComparer.Descending()Descending의 인스턴스를 반환합니다.

모두 IComparer을 구현하더라도이 인스턴스의 유형은 다릅니다. 둘 중 하나를 IComparer으로 전송하면 결과 개체의 유형은 IComparer입니다. 이제 암시 적 변환을 수행 할 수 있습니다. 하나는 인터페이스이고 다른 하나는이를 구현하는 클래스입니다.

는 조건식를 들어, 문서를 인용

condition ?: first_expression : second_expression 

어느 first_expressionsecond_expression의 유형이 동일해야합니다, 또는 암시 적 변환 한 유형에서 다른 존재해야합니다.