96

我是C#(和OOP)的新手。当我有如下代码时:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

问题 1:如果我有其他代码可以做到这一点:

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

Employee是 a Manager,但是当我像这样将它转换为 anEmployee时,这意味着我正在向上转换它吗?

问题 2

当我有几个Employee类对象并且其中一些但不是全部是Manager's 时,我怎样才能在可能的情况下向下转换它们?

4

6 回答 6

104
  1. 那是对的。当您这样做时,您将其转换为一个employee对象,这意味着您无法访问任何特定于管理器的内容。

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

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    

或使用这样的as操作员:

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

如果有什么不清楚的地方,我很乐意纠正它!

于 2009-10-06T08:09:29.513 回答
51

向上转换(使用(Employee)someInstance)通常很容易,因为编译器可以在编译时告诉您一个类型是否是从另一个派生的。

然而,向下转换通常必须在运行时完成,因为编译器可能并不总是知道所讨论的实例是否属于给定的类型。C# 为此提供了两个运算符 -告诉您向下转换是否有效,并返回真/假。并且as which 尝试进行强制转换并在可能的情况下返回正确的类型,否则返回 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");
于 2009-10-06T08:10:13.267 回答
18
  • 向上转型是一种从子类引用创建基类引用的操作。(子类 -> 超类)(即经理 -> 员工)
  • 向下转换是从基类引用创建子类引用的操作。(超类 -> 子类)(即员工 -> 经理)

在你的情况下

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

你正在做一个向上转换。

与需要显式转换的向下转换不同,向上转换总是成功,因为它可能在运行时失败。(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 

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

于 2015-09-28T13:48:34.613 回答
7

如果您需要检查每个 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..
}
于 2014-01-22T18:05:35.997 回答
3

答案 1:是的,它称为向上转型,但你这样做的方式不是现代方式。向上转换可以隐式执行,您不需要任何转换。所以只要写Employee emp = mgr; 足以向上转换。

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

But if we create object of Employee class we can not say that this employee is manager because class Employee is a class which is not inheriting any other class. So you can not directly downcast that Employee Class object to Manager Class object.

So answer is, if you want to downcast from Employee Class object to Manager Class object, first you must have object of Manager Class first then you can upcast it and then you can downcast it.

于 2019-05-03T05:44:45.617 回答
0

向上转换和向下转换:

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

让我们理解为相同的例子:

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

class Shape
{
    public int Width { get; set; }
    public int Height { get; set; }
}

class Circle : Shape
{
    public int Radius { get; set; }
    public bool FillColor { get; set; }
}

向上转换:

形状 s = 新形状();

圆 c=s;

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

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

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

在这里, FileStreamReader() 向上转换为 stradm reder。

向下转型:

形状 s = new Circle(); 在这里,如上所述,s 的视图是唯一的父级,为了使其同时适用于父级和子级,我们需要对其进行向下转换

var c = (圆) s;

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

于 2018-01-26T20:53:03.200 回答