2012-12-11 7 views
18

Zobacz następujący prosty przykład rzucania:Coś o dziedziczeniu/rzucaniu .NET, którego nie rozumiem?

int i = 1000; 
object o = (object)i; // cast 

i.CompareTo(1000); 
o.CompareTo(1000); // error 

rozumiem dlaczego ostatnia linia generuje błąd. W przeciwieństwie do ints, obiekty nie implementują IComparable i dlatego nie ujawniają metody CompareTo. Następujące generuje również błąd:

string s = (string)i; // cast error 

Ponieważ nie ma dziedzictwa między int i strun, casting nie będzie działać tutaj. Teraz spójrz na to:

AudioRender a = new AudioRender(); 
IBaseFilter b = (IBaseFilter)a; // cast 

a.Run(1000); // error 
b.Run(1000); 

(Klasy te pochodzą z DirectShowNet library.)

ja tego nie rozumiem. Obsada nie generuje błędu i nie rzuca żadnych wyjątków w czasie wykonywania, więc zakładam, że AudioRender implementuje IBaseFilter. Jednak AudioRender nie narażać żadnej z metod IBaseFilter za wskazując, że moje założenie powyżej, jest źle ...

jeśli a narzędzi b, dlaczego nie a narazić metod b?
Inaczej, jeśli a nie implementuje b, dlaczego można odlać a na b?
Czy mogę odtworzyć to zachowanie bez użycia DirectShowNet?

Odpowiedz

15

Jest prawdopodobne, że AudioRender implementuje Conversion Operator.

Jednak po przejrzeniu kodu wydaje się, że zarówno AudioRender i IBaseFilter są Com Import:

[ComImport, Guid("e30629d1-27e5-11ce-875d-00608cb78066")] 
public class AudioRender { } 


[ComImport, ("56a86895-0ad4-11ce-b03a-0020af0ba770"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IBaseFilter { .. } 

Jak widać klasa import AudioRender nie implementuje IBaseFilter, więc nie będzie widać go w intellisense, ale jest prawdopodobne, że obiekt COM implementuje ten obiekt COM, dlatego można go przesyłać.

+0

Nawet jeśli tak, to w jaki sposób to robi Odpowiedz na pytanie? – Oded

+0

, ponieważ pozwoliłoby to rzutować na inny typ bez tego, że jest to typ bazowy. –

+0

Oczywiście, ale nie to widzi OP. OP otrzymuje błąd, bez którego nie rzucają. To, co powiedziałeś, nie wymaga wcale rzucania. – Oded

6

Bez zobaczenia kodu źródłowego typów, myślę AudioRender implementuje interfejs IBaseFilterexplicitly, więc nie będzie widać metody interfejsu w IntelliSense na AudioRender.

+0

kod został opublikowany przez @jarek –

14

Trudno powiedzieć bez dostępu do dokumentacji klasy AudioRender, ale rozsądne jest przypuszczenie, że implementacja Run na nim jest explicit interface implementation.

public AudioRender : IBaseFilter 
{ 
    IBaseFilter.Run(...) {...} 
} 

Oznacza to, że można tylko uzyskać dostęp do metody Run gdy masz do niego dostęp za pośrednictwem IBaseFilter odniesienia.

+1

+1 dla jawnej implementacji interfejsu, nie wiedziałem, że było to możliwe w .NET. Gdybym tylko mógł przyjąć wiele odpowiedzi. –

2

If a implements b, why doesn't a expose the methods of b?

można to osiągnąć przez implementing explicitly the interfaces

Else, if a does not implement b, why can a be casted to b?

Ponieważ istotnie a realizuje b.

Also, can I reproduce this behaviour without the use of DirectShowNet?

Tak na pewno można znaleźć ten przykład z powyższego linku (obj.Paint() jest błąd kompilatora):

interface IControl 
    { 
     void Paint(); 
    } 

    public class SampleClass : IControl 
    { 
     void IControl.Paint() 
     { 
      System.Console.WriteLine("IControl.Paint"); 
     } 
    } 

void doit(){ 
    SampleClass obj = new SampleClass(); 
    //obj.Paint(); // Compiler error. 

    IControl c = (IControl)obj; 
    c.Paint(); // Calls IControl.Paint on SampleClass. 
}