沮丧和向上倾斜

时间:2009-10-06 08:03:47

标签: c# oop downcast upcasting

我是 C#(以及 OOP )的新手。当我有一些如下代码时:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

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

   Manager mgr = new Manager();
   Employee emp = (Employee)mgr;

此处EmployeeManager,但当我将其转换为Employee时,这意味着我正在向上转播它?

问题2

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

6 个答案:

答案 0 :(得分:79)

  1. 这是对的。执行此操作时,您将其转换为employee对象,这意味着您无法访问任何特定于经理的内容。

  2. 向下转换是您获取基类然后尝试将其转换为更具体的类的位置。这可以通过使用is和这样的显式转换来实现:

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    
  3. 或使用as运算符,如下所示:

    Manager m = (employee as Manager);
    if (m != null)
    {
        //do something with it
    }
    

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

答案 1 :(得分:47)

向上转换(使用(Employee)someInstance)通常很简单,因为编译器可以在编译时告诉您类型是否来自另一个类型。

然而,

向下转换通常必须在运行时完成,因为编译器可能并不总是知道所讨论的实例是否是给定的类型。 C#为此提供了两个运算符 - ,它告诉您downcast是否有效,并返回true / false。并且 as 会尝试执行转换并在可能的情况下返回正确的类型,否则返回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");

您也可以使用此

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");

答案 2 :(得分:9)

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

在你的情况下

Employee emp = (Employee)mgr; //mgr is Manager

你正在进行预告。

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

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

从:

开始
Employee e = new Employee();

第一:

Manager m = e as Manager; // if downcast fails m is null; no exception thrown

第二

if (e is Manager){...} // the predicate is false if the downcast is not possible 

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

答案 3 :(得分: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..
}

答案 4 :(得分:0)

答案1:   是的,它称为“转换”,但您的操作方式不是现代方式。可以隐式执行向上转换,无需任何转换。因此,只需编写 Employee emp = mgr; 足以进行投射。

答案2:   如果创建Manager类的对象,我们可以说经理是雇员。因为 Class Manager:Employee 描述了Employee Class和Manager Class之间的 Is-A关系。所以我们可以说每个经理都是雇员。

但是,如果我们创建Employee类的对象,则不能说此雇员是经理,因为 class Employee 是不继承任何其他类的类。因此,您不能直接将Employee Class对象转换为Manager Class对象。

因此,答案是,如果要从Employee Class对象下放到Manager Class对象,首先必须具有Manager Class的对象,然后才能上载,然后再下放。

答案 5 :(得分:-1)

向上转发和向下倾斜:

向上转换:从派生类转换为基类 向下转换:从基类转换为派生类

让我们理解同样的例子:

考虑两个类Shape作为我的父类,Circle作为Derived类,定义如下:

CREATE PROCEDURE dbo.procedure (@var int)  
AS
BEGIN
    SELECT * FROM dbo.function(@var)
END

<强>向上转型:

Shape s = new Shape();

圈c = s;

c和s都引用相同的内存位置,但它们都有不同的视图,即使用“c”引用,你也可以访问基类和派生类的所有属性,但使用“s”引用你可以访问唯一父类的属性。

上传的一个实际例子是Stream类,它是.net框架的所有类型的流阅读器的基类:

StreamReader reader = new StreamReader(new FileStreamReader());

这里,FileStreamReader()被上传到streadm reder。

<强>向下转换:

Shape s = new Circle(); 在这里,如上所述,s的视图是唯一的父母,为了使父母和孩子同时我们需要向下传播它

var c =(Circle)s;

Downcasting的实际示例是WPF的按钮类。