18

请参阅以下简单的转换示例:

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

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

我明白为什么最后一行会产生错误。与整数不同,对象不实现IComparable,因此不公开CompareTo方法。以下也会产生错误:

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

由于整数和字符串之间没有继承关系,因此强制转换在这里不起作用。现在,看看这个:

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

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

这些类来自DirectShowNet 库

我不明白这一点。强制转换不会产生错误并且在运行时不会抛出异常,所以我假设 AudioRender 实现了 IBaseFilter。但是AudioRender没有暴露任何IBaseFilter的方法,说明我上面的假设是错误的……

如果aimplements b,为什么不a公开 的方法b
否则,如果a不执行b,为什么会a被强制转换为b
另外,我可以在不使用 DirectShowNet 的情况下重现此行为吗?

4

4 回答 4

15

AudioRender 很可能实现了Conversion Operator

但是,查看代码后,AudioRender 和 IBaseFilter 似乎都是 Com Imports:

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


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

如您所见,AudioRender 导入类未实现 IBaseFilter,因此您不会在智能感知中看到它,但很可能底层 COM 对象实现了它,因此您可以强制转换。

于 2012-12-11T10:17:50.757 回答
14

It is difficult to tell without access to the documentation of the AudioRender class, but a reasonable guess would be that the implementation of Run on it is a explicit interface implementation.

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

That means you can only access the Run method when you access it through a IBaseFilter reference.

于 2012-12-11T10:18:17.413 回答
6

没有看到类型的源代码,我认为显式地AudioRender实现了接口,所以你不会在 IntelliSense 上看到接口的方法。IBaseFilter AudioRender

于 2012-12-11T10:17:07.477 回答
2

如果a实现了b,为什么a不公开b的方法?

这可以通过显式实现接口来实现

否则,如果 a 没有实现 b,为什么 a 可以强制转换为 b?

因为确实a实现了b

另外,我可以在不使用 DirectShowNet 的情况下重现此行为吗?

是的,你可以,从上面的链接中看到这个例子(obj.Paint()是编译器错误):

    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.
}
于 2012-12-11T10:37:41.270 回答