如何在 C# 中将父级转换为子级 [英] How it is possible to cast parent to child in c#

查看:56
本文介绍了如何在 C# 中将父级转换为子级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天前在一次采访中,我被要求解释以下案例:

A few days ago in an interview, i was asked to explain following cases:

public class Parent
{

}
public class Child:Parent
{

}

案例 1:

Parent p = new Child();
    var c = (Child)p;

案例 2:

    Parent p = new Parent();
    var c = (Child)p;

我说case1有效而case2无效,但他问:

I said case1 is valid and case2 is invalid , but he asked:

为什么case2无效而case1case2中的p变量Parent 类的类型是什么?

Why case2 is invalid while both p variable in case1 and case2 are Type of Parent class?

在 case2 中,我们通过以下消息获得运行时异常:

In case2 we get runtime exception by following message:

无法将Parent"类型的对象转换为Child"类型

Unable to cast object of type 'Parent' to type 'Child

虽然在 case1 p 变量也是 Parent 类的类型.

While in case1 p variable was also type of Parent class.

他要我从stackheap内存的角度来解释.

He wanted me to explain it from point of stack and heap memory.

你有什么想法吗?

更新:

面试官误导我的地方正是他在这两种情况下所说的 p 是父"类的类型,根据答案,两个变量的静态类型都是父",但在运行时它们有不同的类型,真正重要的是运行时类型.

The very spot that interviewer misguided me was exactly where he said in both cases p is type of 'parent' class, based on the answers, just static types of both variables are 'parent', but in run-time they have different types and it's run-time type that really matters.

推荐答案

您必须区分变量的静态类型(编译时已知的类型)和分配给变量的对象引用的运行时类型.

You must make a distinction between the static type of a variable (the type known at compile time) and the run time type of an object reference assigned to a variable.

p 的静态类型在这两种情况下都是 Parent,因为它被声明为 Parent p.不管你给它分配了什么.你甚至可以给它赋值null.

The static type of p is Parent in both cases because it is declared as Parent p. No matter what you assign it. You may even assign it null.

赋值后p的值的运行时类型在第一种情况下是Child,在第二种情况下是Parent.p 是否为 null 是不确定的.

The run time type of the value of p after the assignment is Child in the first case and Parent in the second case. It would be undetermined if p was null.

可以将 Child 分配给 Parent,因为 Child 类派生自 Parent.因此,ChildParent(在 OO 术语中).

It is okay to assign a Child to a Parent, because the Child class derives from Parent. A Child is therefore a Parent (in OO terms).

然而,Parent 不是 Child,因为它不是从它派生的.因此,在第二种情况下,您不能将 p 转换为 Child.在第一种情况下,强制转换是有效的,因为您将对象强制转换为其实际运行时类型.它告诉编译器,我知道分配给 Parent 变量的这个对象是一个 Child,所以,请把它当作一个 Child.这不涉及任何转换;但是,如果不允许强制转换,则会执行运行时检查,可能会引发异常.

However, a Parent is not a Child, because it does not derive from it. Therefore, in the second case, you cannot cast p to Child. In the first case the cast is valid, because you cast the object to its actual run time type. It tells the compiler, I know that this object assigned to a Parent variable is a Child, so, please, treat it as a Child. This does not involve any conversion; however, a runtime check will be performed, possibly throwing an exception, if the cast was not allowed.

你被要求从堆栈和堆内存的角度解释它.我很抱歉地说,但这与堆栈或堆内存完全无关.它与继承规则和赋值兼容性有关.

You were asked to explain it from point of view of stack and heap memory. I'm sorry to say, but this has absolutely nothing to do with stack or heap memory. It has to do with inheritance rules and assignment compatibility.

当然,这里我们处理的是引用类型(类).这允许我们从 Parent 派生 Child.这对于值类型(结构)是不可能的.重点是引用类型与值类型,而不是堆与堆栈,这是一个实现细节.顺便说一句,类中的值类型(结构)字段也将存储在堆中.

Of course, here we are dealing with reference types (classes). This allows us to derive Child from Parent. This would not be possible with value types (structs). The point is reference type versus value type, not heap versus stack, which is an implementation detail. And btw., a value type (struct) field in a class will also be stored on the heap.

另见:堆栈是一个实现细节,第一部分两个(Eric Lippert 的博客)

See also: The Stack Is An Implementation Detail, Part One and Two (Eric Lippert's blog)

您没有要求它,但是转换为派生类型之前通常会进行类型测试,因为您通常事先不知道运行时类型.假设 Child 类添加了一个新方法 DriveParentsToDespair()(只有孩子可以这样做).然后你可以使用 使用模式匹配进行类型测试 测试类型并同时将其分配给新变量:

You did not ask for it but casting to a derived type is mostly preceded by a type test, because you usually do not know the run time type in advance. Let us say that the Child class adds a new method DriveParentsToDespair() (only children can do this). Then you could use Type testing with pattern matching to test the type and assign it to a new variable at the same time:

if (p is Child child) {
    child.DriveParentsToDespair();
}

这避免了在 p 的运行时类型为 Parent 的情况下的异常.

This avoids an exception in case p has a run time type of Parent.

这篇关于如何在 C# 中将父级转换为子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆