2009-04-19 2 views
3

개체에 문자열을 업 캐스트 할 수 있지만 IList 개체에 IList 문자열을 업 캐스트 할 수 없습니다. 어째서? 새로운 IList에 모든 항목을 복사하는 지금해야 할 일은 무엇입니까?C# : 제네릭 내에서 캐스팅하지 않습니까?

static void ThisWorks() 
{ 
    IList<object> list = new List<object>(); 
    list.Add("I can add a string since string : object"); 
} 

static void ThisDoesNotWork() 
{ 
    // throws an invalid cast exception 
    IList<object> list = (IList<object>) new List<string>(); 

    list.Add("I'm never getting here ... why?"); 
} 

답변

4

봐 : 바나나는 과일 인 반면, 바나나 바구니는 당신이 오렌지를 추가 할 수 있기 때문에, 과일 바구니 아니다 후자는 아니지만 전자는 아닙니다. List<string>에는 List<object>보다 강력한 제한 조건이 있습니다.

캐스팅은 항상 Liskow이어야합니다. 수정을 허용하지 않는 컨테이너 및 반복자의 경우 이러한 캐스팅은 안전하지만 일을 변경하면 얇은 얼음에 가까운 스케이트를 타게됩니다.

+0

이것은 LSP를 존중합니다 : * 더 * 파생 된 유형 (문자열)을 * 적은 * 파생 된 유형 (객체)으로 취급합니다. 일반적으로 이것은 안전한 것으로 생각됩니다. –

+0

아니요. 그는 바나나 바구니에서 과일 바구니를 만들려고합니다. 그가 독서를하는 동안은 안전하지만 문자열이 추가되지 않으면 이상하게됩니다. –

+1

사실, 이는 ** safe ** generic co/contravariance를 지원하는 C# 4.0과 같은 일부 경우에서 가능할 수 있으므로 예제가 완전히 사실이 아닙니다. –

7

제네릭이 불변하므로 (C# 3.0 기준) 불가능합니다. 그들은 관련이없는 종류 IList<object>에서 상속하지 않습니다 object하지만 IList<string>에서

var objectList = list.Cast<object>().ToList(); 
+0

제네릭이 * 불변이라고 말할 수 있습니다. 그들은 공변하지 않습니다 *. 그들은 C# 4에있을 것이다. –

+0

그래, 방금 알아 챘고 이미 고쳐 놨어. –

+0

@ 존 : C# 4에서도 어떤 것들은 공변량 일거야. 특히, 클래스는 변종이 될 수 없습니다 - 오직 델리게이트와 인터페이스 만. –

1

string 상속 및 그 당신은 그들 사이에 캐스팅 할 수 없습니다

당신은 그것을 해결할 수 있습니다.

그냥이 일을하면 무슨 일이 일어날 지 생각이 같은 그것에

// THIS CODE DOES NOT WORK 
IList<object> list = new List<string>(); // this doesn't compile 
list.Add(5); // because this is perfectly valid on IList<object> but not on IList<string> 
4

질문하신 내용은 본질적으로 의 공분협 및 공분산입니다. 이것은 프로그래밍 언어 디자인의 개념으로, 동일한 상속 계층에서 두 클래스의 객체와 관련하여 메소드와 컬렉션이 작동하는 방식에 대해 설명합니다. Wikipedia article을 읽으면 위의 호기심을보다 크고 일반적인 관점으로 볼 수 있습니다.