2013-04-30 2 views
4

public virtualB.Test()으로 선언 된 A.Test()private new으로 선언되었습니다.
나는 B을 상속하는 C에서 base.Test()을 호출합니다.이 C# 코드는 합법적입니까?

이 코드는 모노 2.10.2로 컴파일하지만 MethodAccessException 발생 :

여기
class A { 
    public virtual void Test() { } 
} 

class B : A { 
    private new void Test() { } 
} 

class C : B { 
    public C() 
    { 
     base.Test(); 
    } 

    public static void Main (string[] args) 
    { 
     var c = new C(); 
    } 
} 

예외 내가 얻을 수있다 :

System.MethodAccessException: Method TestBug.B:Test() is inaccessible from method TestBug.C:.ctor()

이 올바른 행동인가?

이 컴파일은 Microsoft .NET 또는 최신 버전의 Mono에서 컴파일됩니까?
C#에서이 것에 대해 뭐라고 말합니까?
C# 버전에 따라 달라 집니까?

+1

하위 클래스에서 'private' 메소드에 액세스 할 수 없습니다. 다른 클래스에서는 숨겨져 있지만 하위 클래스에서는 사용할 수있게하려면'protected'를 사용해야합니다. –

+0

뭐 하시겠습니까? 손자 클래스 C에서 공개 A. 테스트 메소드에 액세스 하시겠습니까? – statueuphemism

+0

사용중인 Mono 버전의 버그 인 것 같습니다. –

답변

12

유효한 C#이지만 Mono 2.10.2 컴파일러는 분명히 잘못된 작업을 수행하고 있습니다.

IL_0008: ldarg.0 
IL_0009: call  instance void A::Test() 

모노 3.0.6.0 컴파일러는 같은 방식으로 작동합니다 다음 MS 컴파일러로, base.Test()에 대한 호출로 컴파일됩니다.

A에 관한 한, B.Test()은 실제로 존재하지 않습니다. 사실

, 섹션 C# 5 스펙 3.7도 너의 매우 유사한 명시 예이다 :

새로운 멤버 선언 만의 범위 내에 유전 부재 숨겨 새로운 회원. 위의 예에서

class Base 
{ 
    public static void F() {} 
} 

class Derived: Base 
{ 
    new private static void F() {} // Hides Base.F in Derived only 
} 

class MoreDerived: Derived 
{ 
    static void G() { F(); }   // Invokes Base.F 
} 

는 파생에서 F 선언베이스로부터 상속 된 F를 숨기는하지만, 파생 새로운 F에서 개인 액세스하기 때문에, 그 범위는 MoreDerived 확장되지 않는다. 따라서 MoreDerived.G의 F() 호출은 유효하며 Base.F를 호출합니다.

나는 강하게 모노 2.10.2 맹목적 B.Test()에 전화를 삽입하는 것으로 의심 - 그것은 개인 방법의 존재를 볼 수 있지만, 그냥 "기본 클래스 메서드를 호출 할"것을 보장하지 때문이다. 그것이 일어날 때, 그것은 실행 시간에 나 빠지게됩니다. B 일 때 C의 컴파일 시간과 실행 시간 사이를 변경하여 Test() ...을 오버라이드 할 수있는 기본 클래스 메서드를 선택하는 것이 흥미로운 방법입니다. 어떤 시점에서 동작이 명확하지 않은지 확인하십시오. 에릭 리 퍼트 (Eric Lippert)는 blog post에서 이것에 대해 이야기합니다.

+0

레벨을 건너 뛰셨습니까? 왜? – Jasmine

+1

@Jasmine : 왜냐하면'B.Test()'는 private이기 때문입니다. 그것은'C'에게도 보이지 않습니다. 'C'는 그것이 존재한다는 것을 모르기 때문에, * 그것이 * 알고있는 메소드를 호출합니다. –

+0

@ 존, 와줘서 고마워! 현재 Mono 3로 업그레이드 할 수 없기 때문에 이것은 정말 유용합니다. 제 경우에는 빠른 수정이'base.Test()'를'this.Test()'로 바꾸는 것입니다 ('C'는'Test'를 오버라이드하지 않으므로 어쨌든 중요하지 않습니다). –

관련 문제