2014-01-31 3 views
3

누군가이 코드 스 니펫이 작동하지 않는 이유를 설명해 주실 수 있습니까? 왜 b에 캐스팅 할 수 없습니까? 나는 공분산과 반항에 대해 생각하고 있었지만, 내가 합의한 한 추상적 인 수업에는 적용 할 수 없다.제네릭을 사용하여 클래스 사이에 캐스팅

컴파일 오류 : 는 'ConsoleApplication1.VMSBase'의 ConsoleApplication1 \ Program.cs

class Program 
{ 
    static void Main(string[] args) 
    { 
     var a = new SVM(); 

     var b = (VMSBase<Model>)a; 
    } 
} 

class SVM : VMSBase<SpecialModel> 
{ 

} 

class VMSBase<TS> : VMBase<TS> where TS : Model 
{ 

} 

class VMBase<T> where T : Model 
{ 
} 

class SpecialModel : Model 
{ 

} 

class Model 
{ 

} 
+1

무엇이 오류입니까? –

+1

확실하지는 않지만,이 주제가 혼란 스럽기 때문에,이 솔루션이'VMSBase '을'VMSBase '으로 바꾸고 있다고 생각합니다. 그것이 작동하지 않으면'in' 한정자가 대신 사용됩니다. –

+0

다음은 [out] 수정 자에 대한 [documentation] (http://msdn.microsoft.com/en-us/library/dd469487.aspx)입니다. –

답변

6

SVMVMSBase<SpecialModel>의 하위 유형이므로 하나로 변환 할 수 있습니다. 제네릭 형식 매개 변수가 VMSBase<T>T불변 때문에

는하지만, VMSBase<SpecialModel>VMSBase<Model> 사이에 다형성 관계가 없습니다. VMSBase<X> 위해서는


은 (는 XY의 하위 유형) VMSBase<Y>의 서브 타입으로, T는 공변이어야한다. out 키워드를 사용하여 공분산으로 표시합니다 : VMSBase<out T>. 그러나이 방법을 사용하면 모든 멤버 (메서드, 속성 등)의 반환 값에 T 만 입력하고을 입력 값 (메서드 인수)으로 사용하지 않으려면 을 사용해야합니다.

또 다른 문제가 있습니다. C#은 인터페이스의 차이 만 허용합니다. 따라서 인터페이스가되도록 VMBase와 VMSBase를 모두 변경해야합니다.

class Program 
{ 
    static void Main(string[] args) 
    { 
     SVM a = new SVM(); 
     var b = a as IVMSBase<Model>; 
    } 
} 

class SVM : IVMSBase<SpecialModel> {} 

interface IVMSBase<out TS> : IVMBase<TS> where TS : Model {} 

interface IVMBase<out T> where T : Model {} 

상세 정보 : Covariance and Contravariance FAQ

1

결론에 유형 'ConsoleApplication1.SVM을'변환 할 수 없습니다가 VMSBase<SpecialModel>VMSBase<Model>과 동일되지 않는 것입니다.

List<ViewBase> list = new List<GridView>(); 

을의 GridView이 ViewBase에서 상속 있지만 :

이이 컴파일되지 않습니다 왜 같은 이유입니다.

언어가 작동하는 방식에 불과합니다. 제네릭의 한계가 있습니다.

0

당신이 법적으로 캐스팅 할 수 상상해보십시오. 우리는 이제 다음 (놀라운 당신이 전에 그것을 본하지 않은 경우) 방식으로 형식 안전성을 무시할 수,

class VMSBase<TS> : VMBase<TS> where TS : Model 
{ 
    public void GobbleUpModel(TS model) 
    { 

    } 
} 

이 사용 : 이제 우리는이 방법이 모델을 먹는 그 정의 상상

//SpecialModel2 is some other subclass of Model, not related to SpecialModel 
SpecialModel2 incompatibleModel; 

var a = new VMSBase<SpecialModel>(); 

var b = (VMSBase<Model>)a; 

//forces a to gobble up a model that is incompatible with SpecialModel 
b.GobbleUpModel(incompatibleModel); 
0

제네릭이 C#에서 변형되지 않은 이유는 입력 문제를 일으킬 수 있기 때문입니다. 예를 들어 VMSBase에 MyProperty라는 T 유형의 속성이 있다고 가정합니다. 캐스팅이 가능하다면 다음과 같이 할 수 있습니다 :

var a = new VMSBase<SpecialModel>(); 
var b = (VMSBase<Model>) a; 
b.MyProperty = new Model(); 

이제 b 값을 설정하기 만하면됩니다.모델의 인스턴스에 대한 MyProperty; 하지만 실제로는 SpecialModel 인 VMSBase에서 예상되는 유형과 일치하지 않습니다.

관련 문제