2013-04-24 4 views
1

그래서 VariableSeries라는 추상 클래스와이 클래스에서 파생 된 Indicator라는 추상 클래스, 그리고 그 추상 클래스를 구현하는 다양한 클래스 (지표라고 부름)가 있습니다. 나는 지표의 목록을 가지고 그것을 사용할 수 있기를 원한다.제네릭 클래스 목록 사용

public class VariableSeries<T> 
{ 
    protected List<T> Series; 
    public int CurrentBar { get; private set; } 

    public T this[int index] 
    { 
     get 
     { 
      if (index > CurrentBar) 
       throw new Exception("Tried to look too far in the past, data does not exist."); 

      return Series[CurrentBar - index]; 
     } 
    } 
    ... 
} 

그리고 VariableSeries에서 파생 된 것 지표 클래스있어 :

public abstract class Indicator<T> : VariableSeries<T> 
{ 
    ... 
} 

가 지금은 다양한 유형의 지표의 목록을 갖고 싶어합니다. 내 첫 번째 아이디어는 목록을 선언하는 것이었지만 실제로는 작동하지 않습니다. 그리고 제네릭 형식을 사용하는 인덱싱을 사용해야하므로 인터페이스를 던지고 캐스트 할 수 없습니다. 주조 방식의

List<???> Indicators = new List<???>(); 
Indicators.Add(new MovingAverage<type is provided dynamically>()); 
do stuff with Indicators[0][0]; 

아마도 일종의 다음을 수행 할 수있는 방법이 있나요

public class MovingAverage<T> : Indicator<double> 
{ 
    ... 
} 

:

그래서 나는 다음과 같은 표시 등 (중 하나)를 가지고 가정 해 봅시다 ((VariableSeries <>) 표시기 [0]) [0]과 같이 유형을 지정하지 않아도 일반 클래스로 변환 할 수 있습니까?

+1

불가능합니다. 컴파일러는'indicators [0] [0]'식의 형식을 어떻게 알 수 있습니까? – Jon

+0

내가 알기 때문에 알 필요가 없기를 바랬습니다. 예를 들어 표현식 표시기 [0] [0]과 동일한 유형이어야하는 DataTable의 열을 만들고이 값을 DataTable에 저장합니다. ... 내 옵션은 무엇입니까? –

+0

어딘가에서 이미 알고있는 유형 정보가 소개되도록 구문을 변경하십시오. '((Indicator ) 인디케이터 [0]) [0]'또는'public object this [int index]'로 작업하십시오. 후자는 복싱/언 박싱을 많이 유도하는 값 유형을 사용하기 때문에 여기에서 정말 좋지 않을 수 있습니다. – Jon

답변

1

List<???>의 은 콘크리트 유형이어야합니다. 이 구체적인 유형은 귀하의 경우 공통적으로 공유되는 basetype 또는 인터페이스 여야합니다.

모든 클래스는 기본 유형 VariableSeries<T>을 공유하지만이 클래스는 구체적/구체적이지 않습니다. 그래서 List<VariableSeries<T>>은 불가능합니다.

모든 지시자가 double이라는 제네릭 유형을 사용하는 경우 List<VariableSeries<double>>을 사용할 수있는 것보다 많이 사용하지만 그럴 수는 없습니다.

질문 : 당신은 그 목록으로 무엇을 할 것입니까? 그들을 반복하고 무엇을해야합니까? 그들의 가치에 대해 물어보십시오. 어떤 가치가 있습니까? 어떤 타입? 두 배? 문자열? 컴파일러는 알 수 없습니다!

하나 개의 솔루션은 다음과 같은 인터페이스를 만들 수 :

public interface IVariableSeries 
{ 
    object this[int index] { get; } 
} 

VariableSeries<T>에 명시 적으로이 인터페이스를 구현하고 목록에서 구체적인 유형으로,이 인터페이스를 사용 List<IVariableSeries>.

+0

후자의 솔루션은 편리하지만 Jon이 위에서 언급했듯이 boxing/unboxing과 관련하여 많은 문제를 제기합니다. 이들 모두를 두 배로 만들려면 길 아래에서 몇 가지 해킹 시도가 필요하지만이 시점에서 바람직한 해결책 인 것 같습니다. –

+0

그건 완전히 맞습니다. (Un) 권투는 여기에 문제가 있습니다. 그러나이 경우에는 다른 방법이 없습니다. 한 가지 해결 방법은 모든 값을 객체에 저장할 수 있습니다. 그런 식으로 그들은 매 요청마다 상자에 넣지 않고 한 번 상자에 넣습니다. 그러나 특정 유형을 사용하여 그 목록 외부의 값에 액세스하려는 경우 유용하지 않다고 생각할 수 있습니다. –

0

모든 클래스에 공통적이며 유형 매개 변수가없는 모든 메소드로 추상 클래스를 구현할 수 있습니다.

그런 다음 List<IUntypedInterface>을 사용하면 모두 함께 사용할 수 있습니다.

0

리플렉션을 사용하여 몇 가지 작업을 수행 할 수 있습니다. 예를 들어, 당신은 다음과 같은 사용하여 동적 T와 이동 평균을 만들 수 있습니다

Type dynamicType = typeof(int); // or any other, e.g. user selected type 
var instance = (dynamic)Activator.CreateInstance(typeof(MovingAverage<>).CreateGenericType(dynamicType)); 

과정의 문제 것은 당신이 컴파일시에 인스턴스의 유형을 알 수 없다는 것입니다. 따라서 메서드를 호출 할 수 없으며 컴파일 할 때 해당 형식을 알 수 없습니다. 물론 캐스팅 할 수 없습니다. 그래서 나는 그것을 역동적으로 감쌌다.어떤 메소드를 호출 할 수 있으며 백그라운드에서 그 타입을 반영하여 호출 한 메소드 서명을 찾습니다.

인스턴스가

typeof(MovingAverage<>).Equals(instance.GetType().GetGenericTypeDefinition()) 

이 인스턴스가 이동 평균의 파생 유형 실제로 때이 false를 반환된다는 점에 유의을 수행하여 MovingAverage<> 경우 당신은 확인할 수 있습니다. 그것도 확인할 수 있지만 좀 더 복잡합니다.

물론 동적 경로를 사용하는 것은 정적 유형 검사에 많이 의존하는 언어에서 위험한 경로입니다. 리팩터링 지원은 없으므로 코드 실행을 많이 테스트해야합니다. 한 오타와 프로그램이 예외를 throw합니다.

또한, .Net 리플렉션에 익숙해지기를 권합니다. 당신은 위험한 세계로 들어서고 있습니다.

+0

아, 역동적 인 해결책은 매우 쉽습니다. 제 생각에 이것은 상당한 성능 저하가 발생합니다. 맞습니까? –

+0

이 부분은 응용 프로그램과 나머지 응용 프로그램을 어떻게 사용할지에 따라 크게 달라집니다. 어떻게 알았 겠어? – Andreas

0

일반 메서드를 추가하고 해당 메서드에 형식을 전달하십시오. 이 코드는 일반적인 방법으로 사용됩니다.

목록 표시기 = 새 List(); 인디케이터. 추가 (새 MovingAverage());