【问题标题】:C# Interface DowncastingC# 接口向下转换
【发布时间】:2021-11-08 14:04:45
【问题描述】:

首先,我对堆栈溢出和 C# 编程非常陌生..

目前正在尝试使用带有 C# 的某些设备制作程序, 但是在他们的 SDK 示例代码中有一些关于接口使用的问题我不明白..

以下是 DLL 中的接口:

interface ICanChannel2 : ICanSocket2, IBalResource, IDisposable
{
 blah blah
}

interface ICanSocket2 : IBalResource, IDisposable
{
 blah blah
}

interface IBalResource : IDisposable
{
  blah blah
}

我实际上看不到界面中的内容,只能看到它们的名称。 以下是它的使用方法:

ICanChannel2 mCanChn = bal.OpenSocket() as ICanChannel2;
// (note that the return type of bal.openSocket() is IBalResource.)

这种情况就像将 IBalResource 强制转换为 ICanChannel2。

ICanChannel2 继承自 IBalResource 、 ICanSocket2 和 IDisposable。

IBalResource 是 ICanChannel2 的基础接口之一,是否可以强制转换? 到 ICanChannel2?

ICanChannel2 也不应该有 ICanSocket2 吗?哪个 IBalResource 没有?

顺便说一句,代码有效,我的大脑停止了..

【问题讨论】:

  • 欢迎来到 StackOverflow。你在这里问什么并不完全清楚。 “可以将 X 转换为 Y” - 你试过吗?发生什么了?为什么这不符合您的预期?
  • 任何实现接口ICanChannel2的类也需要实现来自ICanSocket2, IBalResource, IDisposable的所有方法——而bal.OpenSocket()返回一个IBalResource,没有人禁止bal.OpenSocket()的实现实际上返回一个东西比 IBalResource 填充更多 - 它必须至少返回一个 IBalResource。如果它返回一些ICanChannel2 实现,你可以做ICanChannel2 mCanChn = bal.OpenSocket() as ICanChannel2;,否则它将为空。
  • 可能需要注意的一点是,您没有将IBalResource 转换为ICanChannel2,而是将bal.OpenSocket() 返回的object 转换为ICanChannel2。该对象可以是实现IBalResource 的任何类,也可以是实现ICanChannel2 的类。请注意,对象属于(是)一个类并实现一个或多个接口。

标签: c# interface casting


【解决方案1】:
interface ISon : IFather
interface ISonB : IFather

public IFather DoSome ( ISon son)
{
    //blah blah...
    IFahter fa = son;// here can cast "automatically" , because "ISon : IFather"
    return fa;
}

ISon son1;
IFather fa = DoSome(son1);
ISon son2 = fa as ISon; // here cast it back. not get a null.
ISonB son3 = fa as ISonB; //here get null, beacause son1 is not a ISonB

【讨论】:

    【解决方案2】:

    首先,如果您使用as 运算符,指令将始终成功,但结果会有所不同。它会投射你的对象,如果可能的话,它会返回null

    目前,当您调用bal.OpenSocket()时,该方法返回一个继承接口IBalResource的对象。你这里有 3 个接口定义,它们都可以一直转换为IBalResource

    因此,您可以使用四个方法OpenSocket() 返回任何继承IBalResourceICanSocket2ICanChannel2 的对象,因为它们都包含IBalResource 中定义的方法

    IBalResource 是 ICanChannel2 的基础接口之一,可以转换为 ICanChannel2 吗?

    IBalResource可以转换成ICanChannel2,如果要转换的对象,当然要继承接口ICanChannel2。但这远远不是被允许的!例如,您可以拥有以下之一:

    class Bal : IBalResource {...}
    
    class Channel : ICanChannel2 {...}
    
    ...
    
    //Assignment is ok, since Bal inherits from IBalResource
    IBalResource balResource = new Bal(); 
    //Assignment is ok, since Channel inherits from ICanChannel2 and ICanChannel2 from IBalResource
    IBalResource channelResource = new Channel(); 
    
    balResource == typeof(ICanChannel2); //false
    channelResource == typeof(ICanChannel2); //true
    

    ICanChannel2 也不应该有 ICanSocket2 吗?哪个 IBalResource 没有?

    是的,ICanChannel2 将有 ICanSocket2 的方法,但也有 IBalResource 的方法。

    希望这可以解决问题。也许您想再次阅读继承。

    顺便说一句。您可以在接口定义中省略许多重定义。

    interface ICanSocket2 : IBalResource, IDisposable
    

    相同
    interface ICanSocket2 : IBalResource
    

    【讨论】:

    • 谢谢大家! :))) @Thomas 非常感谢您的回答!我还想问一件事:“IBalResource 可以转换为ICanChannel2,如果你想转换的对象,当然继承接口ICanChannel2。”我要转换的IBalResource 不继承接口ICanChannel2ICanChannel2 继承IBalResource .. 然后ICanChannel2 可以转换为IBalResource,因为ICanChannel2 继承IBalResource,理解, ,但IBalResource 不能转换为ICanChannel2,因为IBalResource 不继承ICanChannel2
    • @IkheeJo 它始终取决于在代码中某处创建的具体对象。如果您有一个仅从 IBalResource 继承的对象,则无法将其强制转换为 ICanChannel2,因为它不匹配所有接口标准。您可以将其想象为将发动机解释为汽车。这行不通,因为汽车的整个车身都不见了。但是将汽车解释为引擎是可以的,因为内置了一个。也许这个代码片段会对你有所帮助:dotnetfiddle.net/cA7HNE
    • 谢谢托马斯!我想我明白了。你是最棒的! :))
    • 非常感谢!我一直在挖掘示例源代码,我认为所有接口继承链都从构造它的实例开始,尽管我看不到上下文。并且该实例继承了所有接口。由于实例继承了所有的接口ICanSocketICanChannelIBalResource等等,所以可以从一个接口转换到另一个接口。你觉得我接近了吗?
    • Thomas 非常感谢你,你帮了大忙!祝福你和 Stack Overflow!
    猜你喜欢
    • 2016-08-17
    • 2010-09-13
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    相关资源
    最近更新 更多