2013-09-27 4 views
4
public interface ITimeable  {} 
public class TimedDoor : ITimeable {} 

public static class Timer 
{ 
    public static void Add(ITimeable obj) 
    { 
     Console.Write("Add with parameter - ITimeable"); 
    } 

    public static void Add(TimedDoor obj) 
    { 
     Console.Write("Add with parameter - TimedDoor"); 
    } 
} 

public class BaseClient<T> where T : ITimeable 
{ 
    public T TimedDoorObject; 
    public virtual void Init() 
    { 
     Timer.Add(TimedDoorObject); 
    } 
} 

public class Client : BaseClient<TimedDoor> 
{ 
    public Client() 
    { 
     TimedDoorObject = new TimedDoor(); 
    } 

    public override void Init() 
    { 
     Timer.Add(TimedDoorObject); 
    } 
} 
Client.Init() 반환 "Add with parameter - TimedDoor"

이 재정의 된 메서드가 호출되는 이유는 무엇입니까?

에서

그러나 클라이언트가 초기화(), 여기에

public class Client : BaseClient<TimedDoor> 
{ 
    public Client() 
    { 
     TimedDoor = new TimedDoor(); 
    } 
} 

, Client.Init() 반환 "Add with parameter - ITimeable"

를 오버라이드 (override)하지 않는 경우 어떻게 이런 일이 무엇입니까? TimedDoorObject은 런타임 중에 두 경우 모두 동일합니다.

+1

C#에서 과부하 해결은 * 메서드 본문 만 제공된 컴파일러에서 수행됩니다. C#에서는 컴파일러가 generic을 생성하는 데 사용할 유형을 알지 못합니다. C# generics는 * generic *이며, 템플릿 코드의 새 복사본이 모든 구성에서 처음부터 분석되는 C++ 에서처럼 * 템플릿 *이 아닙니다. –

+1

두 경우에'Init' 메소드가 리턴하는 코드를 설명 할 때 문자열을 바꾼 것으로 보입니다. –

+0

@JeppeStigNielsen이 수정되었습니다. 감사합니다 – db42

답변

8

T이 나타내는 점을 명시한 캐스트를 추가하면 Timer.Add(TimedDoorObject)이라는 점이 더 명확하게 나타납니다.

public class BaseClient<T> where T : ITimeable 
{ 
    public T TimedDoorObject; 
    public virtual void Init() 
    { 
     Timer.Add((ITimeable)TimedDoorObject); 
    } 
} 

public class Client : BaseClient<TimedDoor> 
{ 
    public Client() 
    { 
     TimedDoorObject = new TimedDoor(); 
    } 

    public override void Init() 
    { 
     Timer.Add((TimedDoor)TimedDoorObject); 
    } 
} 

그래서 BaseClient 그것이 T 것을 알고 모두를 준수 할 때 ITimeable 객체의 일종이다, 그래서에 링크 할 수있는 최선의 과부하는 void Add(ITimeable obj) 버전입니다. 반대로 컴파일 시간이 Client 인 경우 TTimedDoor을 나타내므로 void Add(TimedDoor obj) 함수를 사용합니다. void Add(ITimeable obj)보다 더 적합하기 때문입니다.

4

TimedDoorObject는 런타임 중에 두 경우 모두 동일합니다.

사실,하지만 방법을 선택한 매개 변수 호출 때와 같이 입력 된 것을 기반으로는 객체 아닌 유형은 현재 가리키는. 따라서, 예를 들어,이 tdTimedDoor에도 불구하고 ITimeable 방법을 부를 것이다 :

TimeDoor td = new TimedDoor(); 
Timer.Add((ITimeable)td); 

를 기본 클래스의 컨텍스트 내에서 TimedDoorObject 필드는 ITimeable으로 입력됩니다. 재정의 된 Init은 파생 클래스의 TimedDoorObject 필드를 참조하며,이 필드는 TimedDoor으로 입력됩니다.

+1

맞습니다. 컴파일 타임 타입이 아닌 실제 런타임 타입이 다른 경우, 그는 가상 메소드 내부에서'Timer.Add ((dynamic) TimedDoorObject); '를 사용할 수 있습니다. 물론 과부하 해결 로직이 런타임에 실행되어야하기 때문에 속도가 느립니다. –

관련 문제