如何在C#中将一个对象向下转型

7

我有以下幻灯片对象列表。根据对象的“类型”变量的值,我希望将列表中的Slide对象向上转型。这是否可行?

foreach(Slide slide in slidePack.slides)
{
    if(slide.type == SlideType.SECTION_MARKER)
    {
      //upcast Slide to Section
    }
}

Section 扩展了 Slide 并增加了一个参数。


听起来像是我要进行向下转型。无论如何,这样做很危险(或者说是设计缺陷)。通过向下转型到更特殊的类型,你期望对象处理更多的事情,而它可能无法处理。如果你感觉需要进行向下转型,请考虑使用接口。 - user1342582
同意接口在某些情况下可能很有用,但我认为我们不应该说“永远不要向下转换”。这并不总是设计缺陷,也不一定危险。 - Allan
7个回答

10

是的,你可以做到这一点:

Section section = (Section)slide;

...或:

Section section = slide as Section;

它们的区别在于,第一个会在 slide 无法转换为 Section 时抛出异常,而第二个则会在无法进行转换时返回 null


7

这是正确的处理转换的方式。

编辑:有一些方法可以设计程序,使其不需要您正在寻找的测试/转换,但如果您遇到需要尝试将C#对象转换为某些类型并根据成功与否以不同的方式处理它的情况,那么这绝对是正确的处理方式。

Section section = slide as Section;
if (section != null)
{
    // you know it's a section
}
else
{
    // you know it's not
}

2
Section section = (Section)slide;

但是你不应该这样做 - 这几乎总是设计有缺陷的迹象。

2

将这个回答放在原帖子的评论区不太合适,我觉得这听起来像是一种向下转型。无论如何,这样做很危险(或者说是设计缺陷)。通过向下转型到更专业的类型,你期望对象能处理更多的事情,但实际上它可能无法胜任。如果你感觉需要进行向下转型,请考虑使用接口。

示例:

class ClassWithX 
{
    public void X() {} 
}

class ClassWithXY 
{ 
    public void X() {} 

    public void Y() {}
}

class Test
{
    public static void Main(string[] args)
    {
        ClassWithX x = new ClassWithX();
        ((ClassWithXY) x).Y(); // Downcast, but x of type ClassWithX does not have Y()
    }
}

希望这能有所帮助。

1

只需简单地进行类型转换:

 Section section = (Section) slide;

1
foreach(Slide slide in slidePack.slides)
{
     if(slide.type == SlideType.SECTION_MARKER)
     {
         Section sec = (Section)slide;

         //use sec.SectionProperty
     }
}

0
如果你只想处理单一类型,也可以这样做。
foreach(Section section in slidePack.slides.OfType<Section>())
{
    // Handle the current section object
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接