2017-09-21 11 views
0

제네릭 클래스를 사용할 때 내 목표를 달성하는 방법을 알고 있습니다. 그러나 제네릭 메서드의 구문이 비 제네릭 클래스에서 (가상 또는 추상으로 선언 될 수 있도록) 허용되는 이유를 이해하려면 결정할 수 없습니다.제네릭 클래스가 아닌 일반 메서드 재정의

코드의 첫 번째 청크는 제네릭 클래스를 사용하여 기본 클래스에서 제한된 인터페이스보다 더 구체적인 인터페이스를 반환하는 추상 메서드를 만드는 간단한 예제를 보여줍니다. 차트 클래스에서 제네릭 형식을 제거하지만, iSeries의 제약으로 일반적인 방법을 유지하는 경우

public interface ISeries 
{ 
    string Name { get; set; } 
    string Color { get; set; } 
} 
public interface ITimeSeries<TY> : ISeries 
{ 
    double[] XValues { get; set; } 
    TY[] YValues { get; set; } 
} 

public interface IPhasorSeries : ISeries 
{ 
    double Magnitude { get; } 
    double Angle { get; } 
} 
public class PhasorSeries : IPhasorSeries 
{ 
    public string Name { get; set; } 
    public string Color { get; set; } 
    public double Magnitude { get; set; } 
    public double Angle { get; set; } 
} 
public class Series<T> : ITimeSeries<T> 
{ 
    public string Name { get; set; } 
    public string Color { get; set; } 
    public double[] XValues { get; set; } 
    public T[] YValues { get; set; } 
} 
public abstract class Chart<T> where T : ISeries 
{ 
    public abstract T GetSeries(); 
} 

public class AnalogChart : Chart<ISeries> 
{ 
    public override ISeries GetSeries() 
    { 
     return new Series<float>(); 
    } 
} 

public class PhasorChart : Chart<IPhasorSeries> 
{ 
    public override IPhasorSeries GetSeries() 
    { 
     return new PhasorSeries(); 
    } 
} 

지금, 나는 다음의 오류를 얻을.

public abstract class Chart 
{ 
    public abstract T GetSeries<T>() where T : ISeries; 
} 

public class AnalogChart : Chart 
{ 
    public override T GetSeries<T>() 
    { 
     // ERROR: 
     // Cannot implicitly convert type Test.Series<float> to 'T' 
     // Cannot convert expression type Test.Series<float> to return type 'T' 
     return new Series<float>(); 
    } 
} 

public class PhasorChart : Chart 
{ 
    public override T GetSeries<T>() 
    { 
     // ERROR: 
     // Cannot implicitly convert type Test.PhasorSeries to 'T' 
     // Cannot convert expression type Test.PhasorSeries to return type 'T' 
     return new PhasorSeries(); 
    } 
} 

는 내가 완전히 비 제네릭 클래스의 일반적인 방법을 구현할 때에 무슨 일이 일어나고 있는지 이해가 안 나타납니다. 제네릭 클래스가 사용되면 - 여러 클래스 정의가 존재합니다. 일반적인 방법 만 사용하면 무엇을 의미합니까? 실제로 여러 가지 방법이 있습니까? 아니면 어떻게 든 그냥 같은 메서드를 호출합니까?

본질적으로 추상적 키워드 및 가상 키워드로 지원되지 않는 경우 추상적 인 제네릭 메소드를 생성 할 때 오류가 발생할 것으로 예상됩니다. 여기에서 구문을 사용하여 다른 코드에서 변환하지 못하게하는 경우 추상 일반 메소드를 올바르게 사용하는 방법은 무엇입니까? (저는 T를 ISeries에 캐스트 할 수 없습니다 - T가 ISeries 여야한다는 것을 모르는 것처럼 하위 클래스에서 제약 조건이 손실 된 것처럼 보입니다)

여기에서 질문의 목적은 이 문제를 해결하지 않거나 다른 '해결 방법'을 제안하지 않을 것입니다.

+0

@juharr : 그건 작동하지 않습니다. 제약 조건은 기본 메서드에서 상속됩니다. – JuanR

답변

-2

원하는 결과를 얻으려면 명시 적 인터페이스 구현을 사용하고 제네릭을 함께 사용하지 않아도된다는 것을 깨달았습니다.

public interface IChart 
{ 
    ISeries GetSeries(); 
} 
public abtract class Chart : IChart 
{ 
    public virtual ISeries GetSeries() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class AnalogChart : Chart, IChart 
{ 
    public new ITimeSeries<float> GetSeries() 
    { 
     return new Series<float>(); 
    } 

    ISeries IChart.GetSeries() 
    { 
     return GetSeries(); 
    } 
} 

public class PhasorChart : Chart, IChart 
{ 
    public new IPhasorSeries GetSeries() 
    { 
     return new PhasorSeries(); 
    } 
    ISeries IChart.GetSeries() 
    { 
     return GetSeries(); 
    } 
} 

이것은 차트 또는 IChart 변수가있는 경우가 iSeries를 받고 있습니다 만, 좀 더 구체적인 유형이있는 경우보다 구체적인 인터페이스를 검색하는 허용한다. 불행히도 그것은 새로운 그것을 만드는 동안 나는 추상을 재정의 할 수없는 것 같습니다, 그래서 던져 추상 클래스 가상 메서드를 사용하여 붙어 있어요.

'GetPhasorSeries', 'GetTimeSeries'메소드를 대신 생성 할 수도 있지만 동일한 메소드 이름을 사용하고 싶었지만이 구체적인 결과를 얻고 싶었습니다.

저는 제네릭이 설계되지 않은 방식으로 굴곡하려고했습니다. 비록 추상적이거나 가상 인 제네릭 메서드를 만드는 이유는 아직 확실하지 않지만. 나는이 패턴을 사용하는 패턴에 대한 아이디어를 환영한다.

0

반환 유형이 T 인 경우 T을 반환해야합니다 (T). 당신은 하드 타입 객체를 반환하고 다음 코드를 할 생각 그것은 T.

의 희망 할 수 그러나, GetSeries의 서명에 따라 유효 코드 것

Series<int> intSeries = angloChart.GetSeries<Series<int>>(); 

, return new Series<float>();이 반환하는 방법으로 허용되지 않는 이유 유형 Series<int>의 변수에 Series<float>을 둘 것입니다 비교하면 방법 당신이 쓴 당신은 일반적인 방법을 사용하면 T

+0

Thanks Sam, T는 ISeries를 구현합니다. 그래서 서브 클래스 메서드의 제네릭 형식을 ITimeSeries로, 그리고 phasor를 IPhasorSeries로 강화하는 방법을 찾고 싶습니다. 그것은 기본 인터페이스의 우산 아래에 하위 인터페이스를 반환 할 수 있어야합니다 것처럼 보입니다 – aitee

0

, 그것은 당신이 콘크리트를 모르는 것을 의미한다 그 유형 T 매개 변수

그렇다면 Series<float>은 어떻게 결정할 수 있습니까?

var ac = new AnalogChart(); 
Series<int> series = ac.GetSeries<Series<int>>(); 

은 일반 클래스와 Series<float>

귀하의 초기 시도를 반환하려는 내부에 있기 때문에 이것은, 캐스팅 오류로 이어질 것 같다 :이 같은이 메서드를 호출에서 저를 방지 무엇

더 나은 접근 방식처럼.

덧붙여서, 컴파일러를 "속여서"처리 할 수는 있지만, 이것은 T의 유형이 될 것이라는 것을 확신하지 않는 한 좋은 생각이 아닙니다 (심지어 다른 전략) :

+0

아, 당신이 말하는 것을 볼 것 같아요. 나는 서브 클래스가 실제로 타입을 지정할 수 없기를 바란다. (당연히 구체적인 타입을 모순이된다.) 내가 원하는 것 것은 : analogChart.GetSeries() => iSeries 및 phasorChart.GetSeries를 (반환) =>를가 iSeries 입니다 IPhasorSeries를 돌려 그러나 나는 그렇게 (유형없이 일반 메소드를 호출 할 수 없기 때문에 기본 클래스는 그것을 정의하지만 하위 클래스는 그것을 강화합니다) 불가능한 구문 인 것처럼 보입니다. – aitee

+0

하위 클래스 구현에서 유형을 강화하는 방법이 있습니까? 그렇지 않은 경우 추상/가상 제네릭 메소드를 허용하는 것은 어리석은 것처럼 보입니다 (유형 T 부분은 절대적으로 쓸모없는 것처럼 보입니다) – aitee