沮丧和向上倾斜

use*_*805 80 c# oop downcast upcasting

我是C#(和OOP)的新手.当我有一些如下代码:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}
Run Code Online (Sandbox Code Playgroud)

问题1:如果我有其他代码执行此操作:

   Manager mgr = new Manager();
   Employee emp = (Employee)mgr;
Run Code Online (Sandbox Code Playgroud)

Employee是一个Manager,但当我把它这样投射到Employee它意味着我正在向上倾斜它?

问题2:

当我有几个Employee类对象时,有些但不是全部都是它们Manager,我怎么能在可能的情况下将它们转发?

RCI*_*CIX 83

  1. 那是正确的.当你这样做时,你将它投射到一个employee对象中,这意味着你无法访问任何经理特定的东西.

  2. 向下转换是指基类,然后尝试将其转换为更具体的类.这可以通过使用is和这样的显式转换来完成:

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    
    Run Code Online (Sandbox Code Playgroud)

或者as像这样的运营商:

Manager m = (employee as Manager);
if (m != null)
{
    //do something with it
}
Run Code Online (Sandbox Code Playgroud)

如果有什么不清楚我会很乐意纠正它!

  • 您的第一条语句(“...将 [Manager 类的实例] 转换为“员工”对象 [..] 意味着您无法访问任何特定于经理的内容”)并不完全准确。在 OP 的示例中,如果 Employee 有一个在 Manager 中被覆盖的虚拟成员,则 CLR 将调用 Manager 实现,尽管进行了转换。来自关于 C# 中多态性的 MSDN 文章:“当派生类覆盖虚拟成员时,即使该类的实例作为基类的实例被访问,也会调用该成员。” MSDN 提供的示例几乎相同。 (4认同)
  • 避免重新定义完善的术语:在OOP和C#的上下文中,"装箱"意味着相当不同的东西(=将值类型对象包装到引用中).此外,您的示例可以(并且应该)使用`as`运算符而不是`is`,然后使用强制转换. (3认同)
  • 我在第一点上更正了,我更改了答案的后半部分以展示两种方法。 (3认同)

Pre*_*gha 47

上传(使用(Employee)someInstance)通常很容易,因为编译器可以在编译时告诉您类型是否来自另一个类型.

然而,向下转换必须在运行时完成,因为编译器可能并不总是知道所讨论的实例是否是给定的类型.C#提供了两个操作人员这一点- 它告诉你,如果垂头丧气的作品,并返回真/假.而作为它试图做演员和返回正确的类型,如果可能的话,则返回null没有.

要测试员工是否是经理:

Employee m = new Manager();
Employee e = new Employee();

if(m is Manager) Console.WriteLine("m is a manager");
if(e is Manager) Console.WriteLine("e is a manager");
Run Code Online (Sandbox Code Playgroud)

你也可以用这个

Employee someEmployee = e  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (e) is a manager");

Employee someEmployee = m  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (m) is a manager");
Run Code Online (Sandbox Code Playgroud)


ove*_*mer 10

  • Upcasting是一种从子类引用创建基类引用的操作.(子类 - >超类)(即经理 - >员工)
  • 向下转换是一种从基类引用创建子类引用的操作.(超类 - >子类)(即员工 - >经理)

在你的情况下

Employee emp = (Employee)mgr; //mgr is Manager
Run Code Online (Sandbox Code Playgroud)

你在做一个向上倾斜.

upcast总是成功,不像需要显式转换的downcast,因为它可能在运行时失败.(InvalidCastException).

C#提供了两个运算符来避免抛出此异常:

从...开始:

Employee e = new Employee();
Run Code Online (Sandbox Code Playgroud)

第一:

Manager m = e as Manager; // if downcast fails m is null; no exception thrown
Run Code Online (Sandbox Code Playgroud)

第二:

if (e is Manager){...} // the predicate is false if the downcast is not possible 
Run Code Online (Sandbox Code Playgroud)

警告:当您进行上传时,您只能访问超类的方法,属性等...


HOK*_*ONG 6

如果您需要检查每个Employee对象是否是Manager对象,请使用OfType方法:

List<Employee> employees = new List<Employee>();

//Code to add some Employee or Manager objects..

var onlyManagers = employees.OfType<Manager>();

foreach (Manager m in onlyManagers) {
  // Do Manager specific thing..
}
Run Code Online (Sandbox Code Playgroud)