为什么要转换为界面?

eft*_*eft 37 c# casting interface

在Jesse Liberty的Programming C#(第142页)中,他提供了一个示例,他将对象转换为接口.

 interface IStorable
 {
    ...
 }

 public class Document : IStorable
 {
    ...
 }

 ...
 IStorable isDoc = (IStorable) doc;  
 ...
Run Code Online (Sandbox Code Playgroud)

这有什么意义,特别是如果对象的类实现了接口呢?

编辑1:澄清一下,我对转换的原因(如果有的话)感兴趣,而不是实现接口的原因.此外,这本书是他的2001年第一版(基于C#1,所以这个例子可能与以后版本的C#没有密切关系).

EDIT2:我在代码中添加了一些上下文

Tun*_*dey 21

因为您希望仅限于接口提供的方法.如果您使用该类,则存在调用不属于接口的方法(无意中)的风险.

  • @Devin:是的,只要将doc声明为实现接口的类型,演员阵容就是多余的. (2认同)

Jer*_*eer 17

实际需要强制转换时只有一个原因:当doc是实现IStorable的实际对象的基本类型时.让我解释:

public class DocBase
{
  public virtual void DoSomething()
  {

  }
}

public class Document : DocBase, IStorable
{
  public override void DoSomething()
  {
    // Some implementation
    base.DoSomething();
  }

  #region IStorable Members

  public void Store()
  {
    // Implement this one aswell..
    throw new NotImplementedException();
  }

  #endregion
}

public class Program
{
  static void Main()
  {
    DocBase doc = new Document();
    // Now you will need a cast to reach IStorable members
    IStorable storable = (IStorable)doc;
  }
}

public interface IStorable
{
  void Store();
}
Run Code Online (Sandbox Code Playgroud)

  • -1,没有解释为什么在编译时已知的类型为了将`IStorable`实现为`IStorable`变量来代替EDIT2时使用强制转换. (5认同)
  • 谢谢,但这让我感到困惑.为什么在创建Document对象时会使用基类型DocBase? (2认同)
  • 可能有许多原因.我所看到的主要是通过实现第三方提供的基类并且没有指定接口.在这种情况下,"DocBase"类来自不同的库,并在您自己的代码中使用接口实现. (2认同)

Jam*_*ran 15

如果对象实现了接口explicit(public void IStorable.StoreThis(...)),那么转换是实际到达接口成员的最简单方法.

  • 它是实现明确实现的接口成员的唯一方式.明确实现的原因是您希望保持类更清晰,因为可能很少使用实现. (3认同)

Ram*_*esh 13

我不确定书中给出的例子在什么情况下.但是,您通常可以将对象类型转换为接口以实现多重继承.我举了下面的例子.

public interface IFoo
{
     void Display();
}
public interface IBar
{
     void Display();
}

public class MyClass : IFoo, IBar
{
    void IBar.Display()
    {
        Console.WriteLine("IBar implementation");
    }
    void IFoo.Display()
    {
        Console.WriteLine("IFoo implementation");
    }
}

public static void Main()
{
    MyClass c = new MyClass();
    IBar b = c as IBar;
    IFoo f = c as IFoo;
    b.Display();
    f.Display();
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

这会显示出来

IBar实现
IFoo实现


Jon*_*eet 10

没有更多的背景,很难说出来.如果doc声明变量是实现接口的类型,则转换是多余的.

你正在阅读哪本书的版本?如果它是"编程C#3.0"我今晚看看我在家时.

编辑:正如我们在答案中看到的那样,这里有三个潜在的问题:

  • 为什么要在问题中显示的语句中进行投射?(答案:如果doc是合适的编译时类型,则不必)
  • 为什么显式强制转换为已实现的接口或基类?(答案:显式接口实现,如另一个答案所示,也是为了在将转换值作为参数传递时选择一个不太具体的重载.)
  • 为什么要使用界面?(答案:使用界面类型意味着您以后不太容易改变具体类型.)

  • 我不知道这是一个有用的信息 - 事实上,它暗示(对我来说)doc变量属于*需要*执行时间检查的类型(这听起来不像这里的情况).那是误导. (3认同)