为什么我们需要在 C# 中进行 Upcasting 和 Downcasting?

D.A*_*fik 1 c# downcast upcasting

考虑我们有三个类,Shape 是基类,另外两个类 Circle 和 Text 继承自基类(Shape)

形状文件

namespace ObjectOriented
{
    public class Shape
    {
        public int Height { get; set; }
        public int Width { get; set; }
        public int X { get; set; }
        public int Y { get; set; }

        public void Draw()
        {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

文本文件

using System;

namespace ObjectOriented
{
    public class Text : Shape
    {
        public string FontType { get; set; }
        public int FontSize { get; set; }

        public void Weirdo()
        {
            Console.WriteLine("Weird stuff");
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

圆.cs

namespace ObjectOriented
{
    public class Circle : Shape
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

我们都知道 Upcasting 总是成功的,我们从子类引用创建对基类的引用

Text txt = new Text();
Shape shape = txt //upcast
Run Code Online (Sandbox Code Playgroud)

和向下转换可能会抛出和InvalidCastException的例如

Text txt = new Text();
Shape shape = txt; //upcast
Circle c = (Circle)shape; //DownCast InvalidCastException
Run Code Online (Sandbox Code Playgroud)

我感到困惑的是,我们可能需要向上/向下转换和对象的情况/情况是什么?

Jer*_*gen 7

通常,您对存储在例如列表中的对象使用向上转换。(共享基类型,甚至Object可以使用)

List<Shape> shapes = new List<Shape>();

shapes.Add((Shape)new Text());    // <-- the upcast is done automatically
shapes.Add(new Circle());
Run Code Online (Sandbox Code Playgroud)

向下转换时,您需要检查它是否是正确的类型:

foreach(Shape shape in shapes)
{
    if(shape is Circle)
    {
        Circle circle = (Circle)shape;
        // do something..
    }

}
Run Code Online (Sandbox Code Playgroud)

一件事是,Circle并且Text都是Shape,但你不能将 a 转换Circle为 a Text。这是因为两个类都在扩展Shape类并添加不同的功能/属性。

例如:有一个CarBike分享他们同基地Vihicle (用于运输人或货物,特别是对土地的事情),但Bike扩展了Vihicle与马鞍和Car扩展与厢体,例如电机。因此,它们不能相互“投射”,但两者都可以视为Vihicle.


有一些有用的扩展方法可以处理类型检查:

foreach(Circle circle in shapes.OfType<Circle>())
{
    // only shapes of type Circle are iterated.
}
Run Code Online (Sandbox Code Playgroud)

“真实世界”示例:

如果你有一个窗口,它上面有很多控件。像标签/按钮/列表视图/等。所有这些控件都存储在其基本类型的集合中。

例如 WPF 控件:所有子控件(在 FrameWorkElement 中)都存储在UIElementCollection. 因此,作为子项添加的所有控件都必须UIElement.

当您迭代所有子控件(UIElement 的)并搜索例如标签时,您必须检查它的类型:

foreach(UIElement element in this.Children)
{
    if(element is Label)
    {
        Label myLabel = (Label)element;
        myLabel.Content = "Hi there!";
    }
}
Run Code Online (Sandbox Code Playgroud)

此循环会将所有标签(在此范围内)更改为“您好!”。