这是如何缩小转换? [英] How is this a narrowing conversion?

查看:66
本文介绍了这是如何缩小转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,当我将person2转换或分配给作为派生类的Employee时,不需要显式转换,但是当将person1分配给employee2时,我需要将其转换为Employee。我的问题是作为派生类的Employee类具有比其基类更多的特性,在这种情况下,我们应该如何以及为什么考虑将person1分配给employee2(需要转换)作为MCSD C#认证工具包书中提到的缩小操作。 br />
事实上,作为祖先的人类具有比Employee更少的功能,因此Employee对象必须能够容纳一个person对象而不需要任何显式转换。请详细说明。



In the Code below when I convert or assign person2 to Employee which is a derived class there is no explicit casting required but when assign person1 to employee2 I need to cast it to Employee. My question is Employee class being a derived class has greater features than its base class, in this case how and why should we consider assigning person1 to employee2 (which requires casting) as a narrowing operation as mentioned in the MCSD C# certification Toolkit book.
Infact person class being ancestor has lesser features than Employee, So Employee object must be able to accommodate a person object without any explicit casting. Please elaborate.

using System.IO;
using System;

class Program
{
    static void Main()
    {
        Employee employee1 = new Employee();
        Person person1 = employee1;
        Console.WriteLine("person1 name:{0}",person1.name);
        Person person2 = new Employee();
        // Allowed because person1 is actually an Employee.
        Employee employee2 = (Employee)person1;

    }
    class Person
    {
       public string name = "Unknown";
       public double salary = 0.00;
    }
    class Employee : Person
    {
      public string Designation = "New Comer";
    }
}

推荐答案

作为祖先的实际人类具有较少的功能比起Employee,所以Employee对象必须能够容纳一个person对象,而不需要任何明确的演员。请详细说明。

不,这是相反的。



因为Employee派生自Person,所以Person变量可以自由地包含Employee(或派生自Person的任何其他类),因为所有这些类必须包含Person类所做的所有事情。因此,系统可以安全地从Person类中访问所有字段,属性,方法,事件等,而不会出现任何问题。



但是请从另一方面邀请运行时错误!让我们举个例子,然后把它转过来:

"Infact person class being ancestor has lesser features than Employee, So Employee object must be able to accommodate a person object without any explicit casting. Please elaborate."
No, it's the other way round.

Because Employee is derived from Person, a Person variable can freely contain an Employee (or any other class derived from Person) because all such classes must contain everything that the Person class does. So the system can safely access all the fields, properties, methods, events, and so forth from the Person class without any problems.

But to go the other way invites run time errors! Let's take your example, and turn it round:
Employee emp = new Person();  // The compiler will complain here, but if it didn't...
string des = emp.Designation;

因为 \\ temp 是指员工,所以可以指定。但是我们为变量分配了一个Person - 它没有一个Designation字段,那么系统应该访问什么?



这就是为什么你必须明确地转换:这样系统可以确定何时访问类实例实际支持它们的派生类功能!如果功能无法使用,则运行时强制转换将失败,因为您无法将Person实例向上转换为派生员工。





考虑以下几行: -

Because emp refers to an Employee, Designation is available. But we assigned a Person to the variable - which doesn't have a Designation field, so what is the system supposed to access?

That's why you have to explicitly cast: so that the system can be sure when it accesses derived class features that the class instance actually supports them! The run time cast will fail if the features will not be available because you can't "up-cast" a Person instance to an derived Employee.


"Considering these lines:-

Employee employee1 = new Employee();
Person person1 = employee1;
Console.WriteLine("person1 name:{0}",person1.name);
Person person2 = new Employee();
// Allowed because person1 is actually an Employee.
Employee employee2 = (Employee)person1;



如果我在WriteLine语句中写person.Designation会抛出编译时错误。但是当我将person1重新分配给Employee对象(employee2)时,employee2可以用来访问指定。现在,当我将employee1分配给person1时,Desig会发生什么民族领域。因为在第一个WriteLine中我永远无法使用person1(自然地)访问指定,因为它是人。但是当我使用person1(已铸造)分配employee2时,会出现在Designation字段中会发生什么。希望你能理解我想说的话。



假设我在员工对象中有数据,我分配给person1,当我在第5天使用person1时,这是否会持续存在声明。这在软件开发实践中是否是一种很好的技术?






如果你写 person.Designation 您收到编译器错误,因为指定不是 Person class - 和 person 是一个可以引用任何 Person 实例的变量 - 所以你只能访问属性,字段等等是每个 Person 的一部分,而不是那些只是派生类的一部分。



当您转换实例时,您不会更改数据,只需更改系统查看数据的方式。任何派生类添加的信息仍然是实例的一部分。



想想汽车。

福特汽车是一辆汽车

嘉年华是一辆福特,这是一辆汽车。

蒙迪欧是福特,这是一辆汽车。



你可以说我的车,意思是嘉年华,蒙迪欧或梅赛德斯A级轿车改变ty你开车的车啊!

同样,你可以说我的福特,意思是节日或蒙迪欧,但是你不能说我的福特并开着梅赛德斯! :笑:



同样的事情适用于你的Person和Employee类:引用实例的变量类型不会改变它引用的实例的类型,它只需控制你可以用它做什么而不将其转换为其他类型。



这是一个非常有用的练习:它允许你创建一个Person类,派生Employee和客户类,并有一个表可以同时容纳两者:


If I write person.Designation in the WriteLine statement it throws a compile time error. But again when I reassign the person1 to Employee object (employee2) the employee2 can be used to access Designation. Now when I assigned the employee1 to person1 what happens to the Designation field. Because in the first WriteLine I could never access Designation using person1(naturally) because it is person. But then what happens to the Designation field which appears back when I assign employee2 with person1(casted). Hope you understand what I intend to say.

Say I had Data in the employee object which I assigned to person1, will that be persistent when I use person1 in the 5th statement. Will this be a good technique in any manner in software development practice?"



If you write person.Designation you get a compiler error, because Designation is not a field of the Person class - and person is a variable which can reference any Person instance - so you an only access properties, fields, and such like that are part of every Person, and not those which are only part of a derived class.

When you cast an instance, you don't change the data, you just change how the system sees the data. Any derived class added information remains a part of the instance.

Think about it with cars.
A Ford is a Car
A Fiesta is a Ford, which is a Car.
A Mondeo is a Ford, which is a Car.

You can say "My Car" and mean a Fiesta, a Mondeo, or a Mercedes A-Class without changing the type of car you drive!
Equally, you can say "My Ford" and mean either a fiesta or a Mondeo, but you can't say "My Ford" and drive away in a Mercedes! :laugh:

The same thing applies to your Person and Employee classes: the variable type that references the instance doesn't change the type of the instance it references, it just controls what you can do with it without casting it to a different type.

It's a very useful practice: it allows you to create a Person class, derive Employee and Customer classes from that, and have a table which can hold both:

List<Person> myList = new List<Person>();
myList.Add(new Employee("Joe Brown"));
myList.Add(new Customer("Mary Shelley"));



Person类具有名称和地址 - 但是Employee将拥有Salary,而Customer将具有DeliveryCost



有意义吗?


The Person class would have the Name and Address - but the Employee would have Salary while the Customer would have DeliveryCost

Make sense?


查看解决方案一。



接口工作一点点不同。它们不是分配到内存中的对象,而只是指向现有对象内存的指针。



看看这个:



See solution one.

Interfaces work a little differently. They are not an object assigned into memory, but just pointers to an existing objects memory.

Take a look at this:

private static void Main()
{
    Employee employee1 = new Employee();
    IPerson person1 = employee1;
    Console.WriteLine("person1 name:{0}", person1.Name);
    Person person2 = new Employee();
    // Allowed because person1 is actually an Employee.
    IPerson employee2 = person2;
    IPerson employee3 = employee1;

    Console.WriteLine("employee2 name:{0}", employee2.Name);
    Console.WriteLine("employee2 name:{0}", employee3.Name);

}

private interface IPerson
{
    string Name { get; set; }
    double Salary { get; set; }

}

private class Person : IPerson
{
    private string name = "Unknown";
    private double salary = 0.00;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public double Salary
    {
        get { return salary; }
        set { salary = value; }
    }
}

private class Employee : Person
{
    public string Designation = "New Comer";
}





我添加了一个接口IPerson,Person实现(通过继承的传递性质,雇员也是如此)



我现在可以使用此界面来表示对象。我可以访问任何作为IPerson的员工或个人的Name对象,但是可以访问。我不得不从IPerson转发给员工。



这留下了一个新问题。 IPerson表示的对象是什么不是Employee对象?我可以施展它,但后来我不知道它是什么开始。我可以使用安全铸造并测试它:





I have added an interface IPerson, which Person implements (by the transitive nature of inheritance, so does Employee)

I can now use this interface to represent the object. I can access the Name object of any employee or person cast as IPerson, but the Designation. I would have to upcast from IPerson to Employee.

This leave a new issue. What is the object represented by IPerson is not an Employee object? I can cast it but then I don't know what it was to begin with. I can use safe casting and test it:

Employee employeeToCheck = employee2 as Employee;
if(employeeToCheck != null)
 {
    //cast successful
 }
else
 {
    //cast failed.  employee2 was not an employee object
 }





您可以使用它来测试,或者您可以检查是声明:



You can use this to test, or you can check the "is" statement:

if(employee2 is Employee)





有很多方法可以使用反射检查类型及其遗传等。



希望有所帮助^ _ ^



Andy



There are lots of ways using reflection to check the type and it's inheritances etc.

Hope that helps ^_^

Andy


这篇关于这是如何缩小转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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