在 C# 中编写向上转型和向下转型表达式
Writing Upcasting and Downcasting expressions in c#
最近在研究c#中的向上转型和向下转型。我知道向上转型是指从派生 class 到基础 class 的转换。然而,当我看到向上转换的实际例子(如下所示)时,我感到困惑。
public class Shape
{
...
}
public class Circle : Shape
{
...
}
Circle circle = new Circle();
Shape shape = new Shape();
// Converting an object into its base class reference
shape = circle
如果我们将 circle 转换成它的基础 class 引用,它不应该像
circle = shape
抱歉,如果听起来太业余了。这是因为我一直看到如下格式的表达式:
int x = 3; // means assign 3 to variable x.
所以我很困惑为什么圆圈在右手边而不是在左手边。请指教。算我一个初学者吧。
你在你的例子中基本上做的也可以写成如下:
Circle circle = new Circle();
Shape shape = (Shape)circle; //Casting the object to the base type
所以您正在将 Circle
类型的对象转换为 Shape
类型的对象。
在您的代码中,这是 "automatically" 完成的,因为您将值分配给类型为 Shape
.
的新变量
这进一步解释了 casting/base 类:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions
(旁白:这被称为 upcasting 因为,传统上,绘制 class 图使得基础 classes 在物理上显示在派生的上方classes.)
现在当你这样做时:
shape = circle; // shape->(instance of Circle)
您正在将 Circle
引用分配给 Shape
引用,以便在分配后引用 shape
将引用 Circle
.
这很好,因为您可以用 Shape
做的所有事情您也可以用 Circle
做。
但是,如果您这样做:
circle = shape; // circle->(instance of Shape)
您正在将 Shape
引用分配给 Circle
引用。您不能这样做,因为(如果可能的话)您将能够访问 Shape
.
中不存在的 Circle
功能
例如,假设 Circle.Radius
存在但 Shape.Radius
不存在。
如果允许您将 circle
引用指向 Shape
如果您尝试访问 circle.Radius
会发生什么?答案是:会发生未定义的行为,因为 Shape.Radius
不存在。
没有
问题是:Shape
不是 Circle
,但 Circle
是 Shape
。
这意味着 Circle
总是可以放在需要 Shape
的地方,但是当你需要 Circle
时,你不能把任何 Shape
因为它也可能是 Triangle
.
这就是为什么你需要明确地转换它(使用 (Type)variable
或 variable as Type
)。
基本上,我们假设如下:
class Shape {}
class Circle : Shape {}
class Triangle : Shape {}
现在,我们还有一个 Triangle
让我们可以更好地实际布局:
Circle c = new Circle();
Triangle t = c; // Impossible due to Circle not being a Triangle
Shape s = c; // Possible because a Circle is a Shape
Triangle t2 = s; // Impossible because Shape may be a Triangle or any other derived class
如果你了解set,你就很容易理解为什么'shape = circle'可以,'circle = shape'不可以。
想想这个。
A是Alphabet的一个字符。
所以我们可以说
public class A : Alphabet
{
}
据我们所知。
Alphabet 也是
public class Alphabet
{
}
如果我们画个图,可以是这样的
┌───────── Alphabet ───────┐
│ A B C D E ... a b c ... z│
└──────────────────────────┘
我们可以说 z 是 Alphabet,但我们不能说 Alplabet 是 z,因为 Alphabet 包含的不仅仅是 z。
所以,让我们看看圆形和形状。
Circle包含了Shape的信息,并且增加了更多的变量。 (可能不是,但可以更改。)
所以我们可以说Circle是一组Shape。
我们可以修改基于Shape的Circle。我们也可以初始化 Circle.
但是如果你这样做'Shape = Circle',Circle中的一些东西无法初始化。
它 returns 错误。
我会尽力解释:
变量shape
包含对类型Shape
对象的引用。
当你写 Shape shape = new Shape();
变量 shape
将包含对新 Shape
对象的引用。
当您通过写入 shape = circle
重新分配 shape
时,它包含对另一个对象的引用。对象circle
的类型是circle
,但是由于circle继承了shape
所以做这个赋值是可以的;对 circle
进行了隐式转换以键入 Shape
.
进行此转换的另一种可能更清晰的方法是进行显式转换:
Circle circle = new Circle();
Shape circleAsShape = (Shape)circle;
向上转型意味着将对象的类型更改为派生较少的基础 class(Circle
对象到 Sape
)。
向下转换在另一个方向起作用,例如。从 Shape
转换为 Circle
.
派生类型多的变量可以很容易地分配给派生类型少的变量,因为这里隐式地进行了向上转换,因为 Circle
也是一个 Shape
。这就是为什么派生类型多的值可以分配给派生类型少的变量。
反之则行不通,因为 Shape
是通用的,我们不知道它是否是 Circle
。因此,当您尝试向下转换时,您需要明确指定它:
// this won't work
Shape shape = new Shape();
Circle c = (Circle)shape;
// this will
Shape shape = new Circle();
// we know we have Circle object so we can downcast
Circle c = (Circle)shape;
最近在研究c#中的向上转型和向下转型。我知道向上转型是指从派生 class 到基础 class 的转换。然而,当我看到向上转换的实际例子(如下所示)时,我感到困惑。
public class Shape
{
...
}
public class Circle : Shape
{
...
}
Circle circle = new Circle();
Shape shape = new Shape();
// Converting an object into its base class reference
shape = circle
如果我们将 circle 转换成它的基础 class 引用,它不应该像
circle = shape
抱歉,如果听起来太业余了。这是因为我一直看到如下格式的表达式:
int x = 3; // means assign 3 to variable x.
所以我很困惑为什么圆圈在右手边而不是在左手边。请指教。算我一个初学者吧。
你在你的例子中基本上做的也可以写成如下:
Circle circle = new Circle();
Shape shape = (Shape)circle; //Casting the object to the base type
所以您正在将 Circle
类型的对象转换为 Shape
类型的对象。
在您的代码中,这是 "automatically" 完成的,因为您将值分配给类型为 Shape
.
这进一步解释了 casting/base 类:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions
(旁白:这被称为 upcasting 因为,传统上,绘制 class 图使得基础 classes 在物理上显示在派生的上方classes.)
现在当你这样做时:
shape = circle; // shape->(instance of Circle)
您正在将 Circle
引用分配给 Shape
引用,以便在分配后引用 shape
将引用 Circle
.
这很好,因为您可以用 Shape
做的所有事情您也可以用 Circle
做。
但是,如果您这样做:
circle = shape; // circle->(instance of Shape)
您正在将 Shape
引用分配给 Circle
引用。您不能这样做,因为(如果可能的话)您将能够访问 Shape
.
Circle
功能
例如,假设 Circle.Radius
存在但 Shape.Radius
不存在。
如果允许您将 circle
引用指向 Shape
如果您尝试访问 circle.Radius
会发生什么?答案是:会发生未定义的行为,因为 Shape.Radius
不存在。
没有
问题是:Shape
不是 Circle
,但 Circle
是 Shape
。
这意味着 Circle
总是可以放在需要 Shape
的地方,但是当你需要 Circle
时,你不能把任何 Shape
因为它也可能是 Triangle
.
这就是为什么你需要明确地转换它(使用 (Type)variable
或 variable as Type
)。
基本上,我们假设如下:
class Shape {}
class Circle : Shape {}
class Triangle : Shape {}
现在,我们还有一个 Triangle
让我们可以更好地实际布局:
Circle c = new Circle();
Triangle t = c; // Impossible due to Circle not being a Triangle
Shape s = c; // Possible because a Circle is a Shape
Triangle t2 = s; // Impossible because Shape may be a Triangle or any other derived class
如果你了解set,你就很容易理解为什么'shape = circle'可以,'circle = shape'不可以。
想想这个。
A是Alphabet的一个字符。
所以我们可以说
public class A : Alphabet
{
}
据我们所知。
Alphabet 也是
public class Alphabet
{
}
如果我们画个图,可以是这样的
┌───────── Alphabet ───────┐
│ A B C D E ... a b c ... z│
└──────────────────────────┘
我们可以说 z 是 Alphabet,但我们不能说 Alplabet 是 z,因为 Alphabet 包含的不仅仅是 z。
所以,让我们看看圆形和形状。
Circle包含了Shape的信息,并且增加了更多的变量。 (可能不是,但可以更改。)
所以我们可以说Circle是一组Shape。
我们可以修改基于Shape的Circle。我们也可以初始化 Circle.
但是如果你这样做'Shape = Circle',Circle中的一些东西无法初始化。
它 returns 错误。
我会尽力解释:
变量shape
包含对类型Shape
对象的引用。
当你写 Shape shape = new Shape();
变量 shape
将包含对新 Shape
对象的引用。
当您通过写入 shape = circle
重新分配 shape
时,它包含对另一个对象的引用。对象circle
的类型是circle
,但是由于circle继承了shape
所以做这个赋值是可以的;对 circle
进行了隐式转换以键入 Shape
.
进行此转换的另一种可能更清晰的方法是进行显式转换:
Circle circle = new Circle();
Shape circleAsShape = (Shape)circle;
向上转型意味着将对象的类型更改为派生较少的基础 class(Circle
对象到 Sape
)。
向下转换在另一个方向起作用,例如。从 Shape
转换为 Circle
.
派生类型多的变量可以很容易地分配给派生类型少的变量,因为这里隐式地进行了向上转换,因为 Circle
也是一个 Shape
。这就是为什么派生类型多的值可以分配给派生类型少的变量。
反之则行不通,因为 Shape
是通用的,我们不知道它是否是 Circle
。因此,当您尝试向下转换时,您需要明确指定它:
// this won't work
Shape shape = new Shape();
Circle c = (Circle)shape;
// this will
Shape shape = new Circle();
// we know we have Circle object so we can downcast
Circle c = (Circle)shape;