2010-07-25 3 views
5

기본적으로 구현하고자하는 것은 제네릭 인터페이스를 구현할 때 구현되는 경우 추가 기능을 제외하고는 T와 똑같이 동작 할 수있는 클래스를 생성하는 것입니다. 여기에 내가 이야기하고있는 예는 다음과 같습니다이 잘하고 좋은C# 인터페이스 : 인터페이스 자체 내에서 인터페이스를 구현하는 유형을 참조 할 수 있습니까?

public interface ICoolInterface<T> 
{ 
    T Value { get; set; } 
    T DoSomethingCool(); 
} 

public class CoolInt : ICoolInterface<int> 
{ 
    private int _value; 

    public CoolInt(int value) 
    { 
     _value = value; 
    } 

    public int Value 
    { 
     get { return _value; } 
     set { _value = value; } 
    } 

    public int DoSomethingCool() 
    { 
     return _value * _value; 
     // Ok, so that wasn't THAT cool 
    } 
} 

그리고,하지만 CoolInt를 사용하기 위해, 나는 이런 식으로 뭔가를 할 필요가 :

CoolInt myCoolInt = new CoolInt(5); 
int myInt = myCoolInt.Value; 

I을 적어도 CoolInt는 int와 똑같이 작동한다는 점에서 많은 것을 배제 할 수 없습니다. 즉 :

CoolInt myCoolInt = 5; 
int myInt = myCoolInt; 

는이를 달성하기 위해, 내 CoolInt 클래스에이 두 가지 변환 연산자를 추가 :

public static implicit operator CoolInt(int val) 
    { 
     return new CoolInt(val); 
    } 

    public static implicit operator int(CoolInt obj) 
    { 
     return obj.Value; 
    } 

는 놀랍도록 작동합니다. 이제 인터페이스에 구현 자들이 이 연산자를 구현하도록이 두 가지 오버로드를 인터페이스에 추가 할 수 있다면이 인터페이스를 선호합니다. 문제는이 연산자의 프로토 타입이 CoolInt를 직접 참조한다는 것입니다.

C#에는 암시 적으로 정의되거나 아직 정의되지 않은 것들에 대한 "자리 표시 자"이름이 많이 있습니다. 일반적인 프로그래밍에서 일반적으로 사용되는 T는 하나의 예입니다. 속성에 사용 된 value 키워드가 다른 키워드라고 가정합니다. "이"참조는 다른 것으로 간주 될 수 있습니다. 인터페이스에 "이 인터페이스를 구현하는 클래스의 유형"을 나타 내기 위해 사용할 수있는 또 다른 심볼이 필요합니다. "구현 자".

public static implicit operator implementer(int val) 
    { 
     return new IntVal(val); 
    } 

    public static implicit operator int(implementer obj) 
    { 
     return obj.Value; 
    } 

이것은 가능합니까?

답변

2

슬프게도 더 :(

는 연산자 오버로딩에 관해서 # 잘하지 않는

C는. 확장 메서드를 대신 사용하지 왜

+0

그렇습니다. 연산자 오버로딩이 작동하지 않는 것은 이상합니다. 여기에 게시 된 추상 일반적인 예에서는 한 가지 방법으로 작동하지만 다른 방식으로는 작동하지 않는 것처럼 보입니다! –

4

abstract class을 만들면 어떨까요? 이렇게하면 클래스에 "기본"기능을 구축 할 수 있습니다.

+1

나는 거기에서 길의 일부를 얻는다 고 생각하지만, 나는 여전히 문제에 부딪 힐 것이라고 생각한다. 제가 AbstractCoolClass를 가지고 있고 구체적인 버전이 이전과 같이 CoolInt라고 가정 해 봅시다. 글쎄, int에서 CoolInt 로의 암시 적 변환 연산자는 AbstractCoolClass 참조를 반환 할 것이며, 이는 CoolInt에 명시 적으로 캐스팅되어야합니다. 나는 명시 적 캐스트없이 오히려 할 것이지만, 선택의 여지가없는 것처럼 보입니다! –

+0

추상 * generic * 클래스는'AbstractCoolClass' 객체를 반환 할 필요가 없으며'T'를 반환 할 수 있습니다. –

+0

두 가지 방법으로 변환해야합니다. 그래서 저는'T'를 받아들이고 클래스의 인스턴스를 반환하는 연산자와, 클래스의 인스턴스를 받아 들여'T'를 반환하는 연산자가 필요합니다. 두 경우 모두, 클래스의 인스턴스에 대한 데이터 유형으로 'AbstractCoolClass'를 사용해야합니다. 후자의 경우, 오버로딩 된 메소드를'AbstractCoolClass'에서 구체적인 클래스 (예 :'CoolInt')로 캐스트하기 만하면되므로 문제가되지 않습니다. 그러나 전의 경우, 나는'AbstractCoolClass'를 리턴해야하고 캐스트를 수행하는 것은 클라이언트 개발자의 몫입니다. –

0

(이것은 하나의 예이고, 다른 하나는 특정 연산자 유형에 대한 일반의 제한) 따라서 다른 유형을 사용하지 않고도 int에 메소드를 "추가"할 수 있습니다.

0

이것은 아마도 추상적 인 기본 유형을 사용하여 얻을 수있는 가장 가까운 것이지만 슬프게도 이것은 암시 적 연산자 및 당신이해야 할 일 : -

 CoolInt x = (CoolInt)5; 
     int j = x; 

충분히 닫습니까?

// Slightly sneaky, we pass both the wrapped class and the wrapping class as type parameters to the generic class 
    // allowing it to create instances of either as necessary. 

    public abstract class CoolClass<T, U> 
     where U : CoolClass<T, U>, new() 
    { 
     public T Value { get; private set; } 

     public abstract T DoSomethingCool(); 

     // Non-public constructor 
     protected CoolClass() 
     { 
     } 

     public CoolClass(T value) 
     { 
      Value = value; 
     } 

     public static implicit operator CoolClass<T, U>(T val) 
     { 
      return new U() { Value = val}; 
     } 

     public static implicit operator T(CoolClass<T, U> obj) 
     { 
      return obj.Value; 
     } 

    } 

    public class CoolInt : CoolClass<int, CoolInt> 
    { 
     public CoolInt() 
     { 
     } 

     public CoolInt(int val) 
      : base(val) 
     { 
     } 

     public override int DoSomethingCool() 
     { 
      return this.Value * this.Value; // Ok, so that wasn't THAT cool 
     } 
    } 
0

적어도 인터페이스의 경우 클래스가 객체를 기준으로 인터페이스를 구현한다고 선언 할 수 있다면 도움이 될 것입니다. "인터페이스"제네릭 형식 제약 조건이 있으면 특히 멋지다. 그런 다음 하나는, 예를 들어, (VB 구문)

 
Class Foo(Of T as Interface) 
    Implements T via Bar ' Declares variable 'bar' of type T 
    Sub DoSomething 
    ' Does something 
    End Sub 
End Class 

그런 짓을 한 후 T에 (T의)는 푸 캐스트와 T. 어쩌면 MS에서 누군가가 아이디어를 비틀 수있는 것처럼 행동 할 수 그것을 전달 하는가?

내가 BTW, 당신의 ICoolInterface 유사한 좋은 패턴주의해야한다

:

 
public interface ISelf<T> 
{ 
    T Self { get;} 
} 
public interface IFoozle 
{ 
    ... definitions for IFoozle 
} 
public interface IFoozle<T> : ISelf<T> , IFoozle; 
{ 
    /* Empty except for above declarations */ 
} 
... similarly define IWoozle and IWoozle<T> etc. 

는 그런 일이 IWoozle 및 IFoozle을 구현할 수있는 필드를 선언 할 수 있습니다, 그리고를 통해, (어느 쪽도 구현하지 않는) BoozleBase에서 상속 :

 
    IWoozle<IFoozle<BoozleBase>> myField1; 
or 
    IFoozle<IWoozle<BoozleBase>> myField2; 

위의 두 유형은 서로 또는 다른 인터페이스를 포함하는 유형으로 형변환 될 수 있습니다. 메서드에 여러 제약 조건을 충족하는 변수 만 전달해야하는 경우 일반 메서드를 사용하여 이러한 제약 조건을보다 쉽게 ​​얻을 수 있습니다. 불행히도, 여러 제약 조건을 가진 일반 함수로 전달 될 수있는 방식으로 알 수없는 유형의 객체를 필드에 저장하는 방법은 없습니다.

관련 문제