2011-12-04 3 views
3

일반 공분산에 묶일 수있는 객체 지향 문제가 있습니다. 나는 모듈은 일반적인 방법을 포함 ... 기록의 다른 유형을 가져 오기위한 모듈 형 시스템을 구축하려고하고 SalesModule 특정 로직을 처리하는 기능을 ...일반 공분산 및 SuperType으로 변환

public interface IImportable { ... void BuildSqlDataRecord(); ... } 
public class Sales : IImportable { ... } 
public interface IModule<out T> where T : IImportable 
{ 
    void Import(IEnumerable<T> list); // Error Occurs here... 
    IEnumerable<T> LoadFromTextFile(TextReader sr); 
} 
public abstract class Module<T> : IModule<T> where T : IImportable 
{ 
    public void Import(IEnumerable<T> list) { ... T.BuildSqlDataRecord(); ... } 
    public IEnumerable<T> LoadFromTextFile(TextReader sr) { ... } 
} 
public class SalesModule : Module<Sales> 
{ 
    public override void BuildSqlDataRecord() { ... }; 
} 

다른 기능에 포함

//Module<IImportable> module = null; 
IModule<IImportable> module = null; 
if(file.Name == "SALES") 
    module = new SalesModule(); 
else 
    module = new InventoryModule(); 

var list = module.LoadFromTextFile(sr); 
module.Import(list); 

어떻게하면 재정의 된 메소드를 호출 할 수있는 모듈을 선언 할 수 있습니까?

답변

10
public interface IModule<out T> where T : IImportable 
{ 
    void Import(IEnumerable<T> list); // Error Occurs here... 
    IEnumerable<T> LoadFromTextFile(TextReader sr); 
} 

오류가 정확합니다. 우리는 T가 "출력"위치에만 나타날 수 있음을 알리는 공분산을 나타내는 키워드로 "out"을 선택했습니다. 하이라이트하는 선에서 T가 입력으로 나타납니다. 음, 허용 된 가정 및 나쁜 일이 일어날 것을 볼 수 ... 때문에

T는 입력을해서는 안 : 당신은 그냥 처리하는 방법을 알고 만 모듈에 호랑이의 목록을 가져

IModule<Giraffe> gm = GetMeAModuleOfGiraffes(); 
IModule<Animal> am = gm; // Legal because of covariance. 
IEnumerable<Tiger> tigers = GetMeASequenceOfTigers(); 
IEnumerable<Animal> animals = tigers; // Legal because of covariance. 
am.Import(animals); // Uh oh. 

기린.

이 문제를 방지하려면 처음 단계가 불법이되어야합니다. 형식 선언은 "out"으로 불법입니다.

어떻게하면 재정의 된 메소드를 호출 할 수있는 모듈을 선언 할 수 있습니까?

공분산 규칙을 ​​준수하도록 인터페이스를 선언해야합니다. 그렇게하는 방법은 당신에게 달려 있지만, "out"매개 변수를 "입력"위치에 두지 않는 것부터 시작하십시오.

+0

좋은 예 ... 자, 리팩터링하는 법 ... :) 고마워! –

3
당신은 당신의 모듈에 대한 인터페이스를 사용해야합니다

:

IModule<IImportable> = null; 

out 일반적인 mdoifier에 대한 here for the MSDN documentation를 참조하십시오

public interface IModule<out T> where T : IImportable 
{ 
    void DoStuff(); 
    void DoOtherStuff(); 
} 

는 그런 다음과 같이 모듈을 선언 할 수 있습니다 .

+0

리치 - 빠른 답변에 감사드립니다. 나는 물건을 바꿀지도 모르는 예제에 약간의 세부 사항을 추가하기 위해 질문을 편집했다. 공변 매개 변수 T가 Import 메서드의 입력 및 LoadFromTextFile의 반환 값으로 사용되므로 변경 내용을 구현하는 것처럼 보이지 않습니다. 나는 완전히 잘못 될 것인가? –