2012-04-04 2 views
7

필자가 필요로하는 멋진 솔루션이 있지만이를 대체 할 우아한 솔루션을 찾고 있습니다.C#의 일반 상속 유형 제한

다음 코드는 컴파일되지 않습니다

,하지만 내가하고 싶은 것을 나타냅니다. ClientHelper<T>T 관계없이 전달 된 템플릿 유형의 BaseClient을 확장하는 클래스 인 경우

interface IWebService 
{ 
} 

abstract class BaseClient<T> 
{ 
} 

class SpecializedClient : BaseClient<IWebService> 
{ 
} 

class ClientHelper<T> where T : BaseClient<*> 
{ 
} 

내가 찾은 세련 솔루션입니다 :

class ClientHelper<T, U> where T : BaseClient<U> {} 

이 우아하게 그 이유는 내 proje입니다 CT는 유사한 클래스와 끝 : 아래 하나의 형식을 취 기본 클래스에

class MyClass<A, B, C, D, E, F, G> where A : MyBaseClass<B, C, D, E, F, G> 

모든 방법을. 이것은 단순히 일반 클래스의 복잡한 상속 트리가있는 비용입니까 아니면 템플릿 기반 유형에 대한 유형 제한을 유지하면서이 작업을 수행하는 더 간단한 방법입니까?

답변

5

BaseClient의 공용 인터페이스가 제네릭 형식 매개 변수를 어떤 식 으로든 노출하는 경우 "세련되지 않은"솔루션이 적합합니다.

그래서 BaseClient 가정은 하지 당신은 그것을 정의 :

abstract class BaseClient<T> 
{ 
    //Something about T here 
} 

그리고 T는 가정, 다시 ClientHelper의 공용 인터페이스 계약 (의 BaseClient의 공개 인터페이스 계약의 일부, 따라서 일부 BaseClient<U>은 ClientHelper의 인터페이스를 통해 노출됩니다.

한편

,의는 실제로 귀하의 예제가 말하듯 가정하자 :이 경우

abstract class BaseClient<T> 
{ 
    //Nothing about T here 
} 

을, 당신은 할 수 있습니다 :

interface IBaseClient 
{ 
    //Nothing about T here 
} 

abstract class BaseClient<T> : IBaseClient 
{ 
    // Whatever you like here 
} 

ClientHelper이된다 :

class ClientHelper<T> where T : IBaseClient 
{ 
} 
+0

내 수업의 일부가 공개적으로 내부적으로 'T'를 공개하지 않으므로 일부 인터페이스에서 인터페이스가 작동 할 수 있습니다. 나는 다루기 힘들어지기 시작하면서 얻을 수있는 단순화를 취할 것이다. – Foran

+0

'클래스 '(여기서'T'는 결코 공개적으로 노출되지 않습니다)의 모든 경우를 단순화했습니다. 간단하면서도 분명히 나는 ​​그것을 볼 수 없었다. :-) 이것은 전달 될 필요가있는 유형의 대략 절반을 잘라냅니다. – Foran

+0

차가움. 다행 이네. 인터페이스에 타입에 의존하지 않는 주어진'T' (메쏘드, 프로퍼티, 이벤트, 필드)에 대해 *** 연산 ***을 모두 일반화 할 수 있다면 몇 가지 추가 일반 매개 변수를 제거 할 수도 있습니다 . –

0

한 옵션이 다음과 같이 보입니다.

interface IWebService 
{ 
} 

interface IClient<out T> 
{ 
} 

abstract class BaseClient<T> : IClient<T> 
{ 
} 

class SpecializedClient : BaseClient<IWebService> 
{ 
} 

class ClientHelper<T> where T : IClient<object> 
{ 
} 

그러나 BaseClientT을 반환하고 허용하지 않는 경우에만 작동합니다.