如何从具体类强制转换为接口类型

本文关键字:转换 接口类型 | 更新日期: 2023-09-27 18:35:48

我正在构建一个多层应用程序。

当我将对象从表示层传递到业务层时,我想将其强制转换为接口类型,因为业务层不知道表示层的具体类。

    public ActionResult SubmitSurvey(SurveyAnswer answers)
    {
        ISurveyAnswer answer = (ISurveyAnswer)answers;
        bc.SaveSurvey(answer);
        return null;
    }

SurveyAnswer实现接口 ISurveyAnswer

当我检查业务层中的类型时:

 public void SaveSurvey(ISurveyAnswer answer)
        {
            String type = answer.GetType().Name;
        }

GetType()。Name 方法返回 SurveyAnswer,它是表示层中的具体类。它应该这样做吗?

如何从具体类强制转换为接口类型

强制转换不会更改对象的类型。 对象始终与创建时相同。 强制转换只是更改用于访问对象的接口。 如果你愿意,它会改变你对对象的"视图"。 不过,这不是问题。 你正在做的事情是正确的。 UI 层关心的只是 ISurveyAnswer 接口,因此只要对象的具体类型实现了该接口,那么一切都很好,并且可以按预期工作。 这样做的好处是,现在 UI 层可以被赋予任何类型的对象(包括模拟对象),这并不重要,只要对象实现相同的接口,UI 就会工作并且不会关心。 GetType 将允许您检查对象以查看对象的实际类型是什么,但在大多数情况下,它对 UI 层无关紧要。 只要提供的对象实现该接口并正常工作,UI 也会正常工作。

当任何类或方法要求将某种类型的对象传递给它时,理想情况下,它应该始终要求尽可能窄的实现或基类型。 例如,如果您有一个采用项目列表的方法,它可能看起来像这样:

void printList(List<Dog> dogs)
{
    foreach(Dog dog in dogs)
        printDog(dog);
}

但是,从技术上讲,该方法实际上并不需要List<>对象,因为它所做的只是枚举列表中的项。 它本身不使用 List<> 类型的任何成员,它只是使用 IEnumerable<> 接口的成员,该接口由 List<> 类型实现。 因此,在这种情况下,最好像这样编写方法:

void printList(IEnumerable<Dog> dogs)
{
    foreach(Dog dog in dogs)
        printDog(dog);
}

现在,如果在方法内部,它不仅需要枚举列表,还需要列表中项目的总数,那么IEnumerable是不够的。 但是,它仍然不需要完整的List<>类型,它只需要ICollection<>类型(也由List<>实现),如下所示:

void printList(ICollection<Dog> dogs)
{
    printTotal(dogs.Count);
    foreach(Dog dog in dogs)
        printDog(dog);
}

但是,如果该方法需要获取每个项目的索引,则ICollection<>是不够的 - 该方法需要IList<>类型。 例如,此示例显示了它如何打印狗列表并突出显示列表中的所有其他狗:

void printList(IList<Dog> dogs)
{
    printTotal(dogs.Count);
    for(Dog dog in dogs)
        if (dogs.IndexOf(dog) % 2 == 0)
            printDog(dog);
        else
            printHighlightedDog(dog);
}

您会注意到,在这些示例中,我都不必将dogs参数转换为其他类型。 我根据需要适当地键入了参数,因此我只是通过该类型的接口使用它。 在所有这些示例中,可以将List<Dog>对象传递到 printList 方法中而无需强制转换(因为 List<> 实现了所有这些接口,因此可以隐式强制转换):

List<Dog> dogs = new List<Dog>();
dogs.Add(new Dog());
printList(dogs);

请记住,这是一个非常简单的例子来说明一个观点。 在现实世界的场景中,由于各种原因,即使您在技术上不需要他们提供的所有内容,您通常也可能只是要求List<>IList<>。 您可能知道该方法将来很可能需要IList<>功能,即使它现在只需要IEnumerable<>功能。 但是,在决定方法参数的类型时,要牢记该原则。

您几乎不需要知道传递给方法的对象的实际类型。 您真正需要知道的是它实现了特定的接口,以便您可以通过该特定接口访问其功能。

我想将其转换为接口类型

没必要。如果具体类型实现了该类型,则无需强制转换它。

这将正常工作:

public ActionResult SubmitSurvey(SurveyAnswer answers)
{
    bc.SaveSurvey(answers);
    return null;
}

GetType()。Name 方法返回 SurveyAnswer,它是表示层中的具体类。它应该这样做吗?

没错。它将返回正在传入的实际类型(无论您将其转换为什么类型)。