铸造不会更改对象的类型。该对象始终与创建时相同。铸造只是改变你通过其访问对象的界面。如果您愿意,它会改变对象的“视图”。不过这不是问题。你在做什么是正确的。所有UI层关心的是ISurveyAnswer接口,只要对象的具体类型实现了该接口,那么一切都会很好,并且可以按照您的预期工作。这样做的好处是,现在UI层可以被赋予任何类型的对象(包括模拟对象),并且无关紧要,只要对象实现了相同的接口,UI将会工作并且不会在意。 GetType可以让你检查对象,看看对象的实际类型是什么,但是在大多数情况下,对UI层来说应该没有关系。只要提供的对象实现了该接口并且正常工作,UI也将如此。
当任何类或方法要求将某种类型的对象传递给它时,理想情况下它应始终要求尽可能最窄的实现或基类型。因此,举例来说,如果你有需要的项目列表的方法,它可能是这个样子:
void printList(List<Dog> dogs)
{
foreach(Dog dog in dogs)
printDog(dog);
}
但是,从技术上讲,该方法并不真的需要一个List<>
对象,因为所有它做的是枚举列表中的项目。它不使用List<>
类型的任何成员,它本身只使用接口的成员,该接口由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);
}
但是,如果方法neededs获得每个项目的索引,ICollection<>
是不够的 - 该方法需要IList<>
类型。例如,这个例子说明它如何打印狗的名单,并强调每隔1个清单:
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<Dog> dogs = new List<Dog>();
dogs.Add(new Dog());
printList(dogs);
请记住,这是一个非常简单的例子来说明一个观点。在现实世界的情况下,即使您技术上不需要他们提供的所有东西,但出于各种原因,您经常可能会要求List<>
或IList<>
。您可能知道该方法未来可能需要IList<>
功能,尽管它现在只需要功能IEnumerable<>
。但是,当你决定你的方法的参数类型时,该原则是一个非常好的原则。
您几乎从不需要知道传入方法的对象的实际类型。您真正需要知道的是它实现了一个特定的接口,以便您可以通过该特定接口访问其功能。
当我在业务层接收对象时,对象的正确操作是什么?我应该将它映射到另一个对象,因为它来自业务层上的一个层?谢谢 – Kenci
@Kenci我添加了一些例子和进一步的解释,希望能为你解决问题。 –