C# - 基础类型的强制转换是如何工作的?

时间:2017-11-08 22:46:37

标签: c# class object casting

这可能是重复的,但我找不到类似的问题。我不明白如何在没有数据丢失的情况下对基类型进行隐式转换。例如,我创建了类Person

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

现在,当我这样做时:

object personAsObject = new Person { Name = "Foo", Age = 1 };
var person = (Person) personAsObject;
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);

object如何保留属性NameAge的值,因为它只包含4种方法EqualsGetHashCode,{ {1}}和GetType?为什么对子类的强制转换抛出ToString?我希望这是可能的,因为如果成员不是私人的话,他们就会被继承。

2 个答案:

答案 0 :(得分:9)

所有关于参考文献。

personAsObject不是对象实例

当您调用new Person时,您在托管内存中创建了Person的实例。

变量personAsObject是一个引用:指向Person对象所在的托管内存位置的指针。

同样适用于person:它不是Person实例,它是对Person的引用(恰好是personAsObject是内存中VARIABLES MANAGED MEMORY ========= ============== personAsObject----| +-----------------+ |---->| Person Instance | person------------| +-----------------+ 引用的同一个对象。

echo

答案 1 :(得分:1)

用一个过度使用的例子来解释 - 这不一定是良好类设计的一个例子:

public class Employee
{
    public string Name { get; set; }
    public Guid EmployeeId { get; set; }
}

public class Manager : Employee
{
    public IEnumerable<Employee> DirectReports { get; set; }
}

如果您将Manager转换为Employee

var manager = GetManager(guid employeeId);
var employee = manager as Employee;

var employee = (Employee)manager;

您没有将Manager变成Employee,因为Manager已经是Employee

实际上,你所说的是你不关心这个对象是什么,而不是Employee。因为在某些情况下你可能不在乎。假设您要创建一个员工列表 - List<Employee> - 接近他们的五周年纪念日,以便您可以邀请他们参加聚会。您可以将每种Employee添加到该列表中,这一点很重要。

这也使多态性成为可能。另一个常见的例子:

public interface IAnimal
{
    string MakeSound();
}

public class Cow : IAnimal
{
    public string MakeSound()
    {
        return "Moo";
    }
}

public class Giraffe : IAnimal
{
    public string MakeSound()
    {
        return "I don't make any sound. Bad example.";
    }
}

现在你可以这样做:

var animals = new List<IAnimal>();
animals.Add(new Cow());
animals.Add(new Giraffe());
foreach(var animal in animals) // or IAnimal in animals
{
    Console.WriteLine(animal.MakeSound());
}

将显示

  


  我没发出任何声音。不好的例子。

当您浏览List<IAnimal>中的项目时,您不知道每个项目的实际课程。您所知道的是,每个项目都是IAnimal并实现MakeSound()。它不会改变每个的“具体”类型。它只是意味着为了你正在做的事情,你不关心具体的类型。

这使各种各样的事情成为可能。你可以拥有这样的课程

public class Cow : IAnimal, ITastesGood
{
    public string MakeSound()
    {
        return "Croak";
    }
}

var cow = new Cow();
var animals = new List<IAnimal>();
var food = new List<ITastesGood>();
animals.Add(cow);
food.Add(cow);

Cow的同一个实例可以转换为它继承的任何类或它实现的任何接口。