【问题标题】:Something about .NET inheritance/casting that I don't understand?我不明白的关于 .NET 继承/转换的东西?
【发布时间】:2012-11-28 20:58:20
【问题描述】:

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

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 library

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

如果a实现了b,为什么a不暴露b的方法呢?
否则,如果a没有实现b,为什么a可以强制转换为b
另外,我可以在不使用 DirectShowNet 的情况下重现此行为吗?

【问题讨论】:

    标签: c# .net inheritance interface casting


    【解决方案1】:

    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 对象实现了它,因此您可以强制转换。

    【讨论】:

    • 即使是这样,那如何回答这个问题?
    • 因为它允许您转换为另一种类型而不是基本类型
    • 当然,但这不是 OP 所看到的。 OP 收到错误除非他们施放。你说的根本不需要施法。
    • 好吧,如果它使用显式转换运算符,则需要您进行转换,但是这种或其他方式,OP 会看到这种行为,因为无论如何类型和接口都是 COM 导入。
    • +1 用于实际查找类型(最终:)),而不仅仅是推测。
    【解决方案2】:

    如果不访问AudioRender 类的文档,很难判断,但合理的猜测是Run 的实现是explicit interface implementation

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

    这意味着您只能通过IBaseFilter 引用访问Run 方法。

    【讨论】:

    • +1 用于显式接口实现,我不知道这在 .NET 中是可能的。如果我能接受多个答案就好了。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      这可以通过implementing explicitly the interfaces实现

      否则,如果 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.
      }
      

      【讨论】:

        猜你喜欢
        • 2019-09-09
        • 2012-06-12
        • 1970-01-01
        • 2021-05-02
        • 1970-01-01
        • 2014-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多