无法从父类转换为子类

时间:2022-02-24 16:12:24

I am trying to cast from a parent class to a child class but I get an InvalidCastException. The child class only has one property of type int. Does anyone know what I need to do?

我试图从父类转换为子类,但我得到一个InvalidCastException。子类只有一个int类型的属性。有谁知道我需要做什么?

12 个解决方案

#1


You can't cast a mammal into a dog - it might be a cat.

你不能把哺乳动物变成狗 - 它可能是一只猫。

You can't cast a food into a sandwich - it might be a cheeseburger.

你不能把食物扔进三明治 - 它可能是一个芝士汉堡。

You can't cast a car into a Ferrari - it might be a Honda, or more specifically, You can't cast a Ferrari 360 Modena to a Ferrari 360 Challange Stradale - there are differnt parts, even though they are both Ferrari 360s.

你不能把汽车变成法拉利 - 它可能是本田,或者更具体地说,你不能将法拉利360摩德纳投射到法拉利360 Challange Stradale--虽然它们都是法拉利360,但它们有不同的部分。

#2


A simple way to downcast in C# is to serialize the parent and then deserialize it into the child.

在C#中向下转换的一种简单方法是序列化父对象,然后将其反序列化为子对象。

 var serializedParent = JsonConvert.SerializeObject(parentInstance); 
 Child c  = JsonConvert.DeserializeObject<Child>(serializedParent);

I have a simple console app that casts animal into dog, using the above two lines of code over here

我有一个简单的控制台应用程序,使用上面两行代码将动物投入狗

#3


The instance that your base class reference is referring to is not an instance of your child class. There's nothing wrong.

基类引用所引用的实例不是子类的实例。没有错。

More specifically:

Base derivedInstance = new Derived();
Base baseInstance = new Base();

Derived good = (Derived)derivedInstance; // OK
Derived fail = (Derived)baseInstance; // Throws InvalidCastException

For the cast to be successful, the instance that you're downcasting must be an instance of the class that you're downcasting to (or at least, the class you're downcasting to must be within the instance's class hierarchy), otherwise the cast will fail.

为了使转换成功,您正在向下转换的实例必须是您正在向下转换的类的实例(或者至少,您要向下转换的类必须在实例的类层次结构中),否则演员会失败。

#4


There are some cases when such a cast would make sense.
I my case, I was receiving a BASE class over the network, and I needed more features to it. So deriving it to handle it on my side with all the bells and whistles I wanted, and casting the received BASE class into the DERIVED one was simply not an option (Throws InvalidCastException of Course)

在某些情况下,这样的演员会有意义。我的情况是,我通过网络接收了一个BASE课程,我需要更多的功能。因此得出它来处理它我所需要的所有铃声和口哨,并将收到的BASE类转换为DERIVED一个根本不是一个选项(抛出InvalidCastException of Course)

One practical think-out-of-the-box SOLUTION was to declare an EXTENSION Helper class that was NOT inheriting BASE class actually, but INCLUDING IT as a member.

一个实用的开箱即用的解决方案是声明一个EXTENSION Helper类,它实际上并没有继承BASE类,而是将它作为成员包含在内。

public class BaseExtension
{
   Base baseInstance;

   public FakeDerived(Base b)
   {
      baseInstance = b;
   }

   //Helper methods and extensions to Base class added here
}

If you have loose coupling and just need a couple of extra features to base class without REALLY having an absolute need of derivation, that could be a quick and simple workaround.

如果你有松散的耦合,只需要一些额外的功能来基类而不必绝对需要派生,那么这可能是一个快速而简单的解决方法。

#5


That would violate object oriented principles. I'd say an elegant solution here and elsewhere in the project is using a object mapping framework like AutoMapper to configure a projection.

这将违反面向对象的原则。我想在这里和项目的其他地方使用像AutoMapper这样的对象映射框架来配置投影。

Here's a slighty more complex configuration than is neccessary but is flexible enough for most cases:

这是一个比必要的更复杂的配置,但对于大多数情况来说足够灵活:

public class BaseToChildMappingProfile : Profile
{
    public override string ProfileName
    {
        get { return "BaseToChildMappingProfile"; }
    }

    protected override void Configure()
    {
        Mapper.CreateMap<BaseClass, ChildClassOne>();
        Mapper.CreateMap<BaseClass, ChildClassTwo>();
    }
}


public class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(x =>
        {
            x.AddProfile<BaseToChildMappingProfile>();
        });
    }
}

When application starts call AutoMapperConfiguration.Configure() and then you can project like this:

当应用程序启动时调用AutoMapperConfiguration.Configure()然后你可以这样投影:

ChildClassOne child = Mapper.Map<BaseClass, ChildClassOne>(baseClass);

Properties are mapped by convention so if the class is inherited the property names are exactly the same and mapping is configured automatically. You can add additional properties by tweaking the configuration. See the documentation .

属性按约定映射,因此如果继承该类,则属性名称完全相同,并自动配置映射。您可以通过调整配置来添加其他属性。请参阅文档。

#6


Paul, you didn't ask 'Can I do it' - I am assuming you want to know how to do it!

保罗,你没有问'我能做到吗' - 我假设你想知道怎么做!

We had to do this on a project - there are many of classes we set up in a generic fashion just once, then initialize properties specific to derived classes. I use VB so my sample is in VB (tough noogies), but I stole the VB sample from this site which also has a better C# version:

我们必须在一个项目上执行此操作 - 我们只以通用方式设置了许多类,然后初始化特定于派生类的属性。我使用VB所以我的样本是在VB(艰难的noogies),但我偷了这个网站的VB样本,它也有一个更好的C#版本:

http://www.eggheadcafe.com/tutorials/aspnet/a4264125-fcb0-4757-9d78-ff541dfbcb56/net-reflection--copy-cl.aspx

Sample code:

Imports System
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Text
Imports System.Diagnostics

Module ClassUtils

    Public Sub CopyProperties(ByVal dst As Object, ByVal src As Object)
        Dim srcProperties() As PropertyInfo = src.GetType.GetProperties
        Dim dstType = dst.GetType

        If srcProperties Is Nothing Or dstType.GetProperties Is Nothing Then
            Return
        End If

        For Each srcProperty As PropertyInfo In srcProperties
            Dim dstProperty As PropertyInfo = dstType.GetProperty(srcProperty.Name)

            If dstProperty IsNot Nothing Then
                If dstProperty.PropertyType.IsAssignableFrom(srcProperty.PropertyType) = True Then
                    dstProperty.SetValue(dst, srcProperty.GetValue(src, Nothing), Nothing)
                End If
            End If
        Next
    End Sub
End Module


Module Module1
    Class base_class
        Dim _bval As Integer
        Public Property bval() As Integer
            Get
                Return _bval
            End Get
            Set(ByVal value As Integer)
                _bval = value
            End Set
        End Property
    End Class
    Class derived_class
        Inherits base_class
        Public _dval As Integer
        Public Property dval() As Integer
            Get
                Return _dval
            End Get
            Set(ByVal value As Integer)
                _dval = value
            End Set
        End Property
    End Class
    Sub Main()
        ' NARROWING CONVERSION TEST
        Dim b As New base_class
        b.bval = 10
        Dim d As derived_class
        'd = CType(b, derived_class) ' invalidcast exception 
        'd = DirectCast(b, derived_class) ' invalidcast exception
        'd = TryCast(b, derived_class) ' returns 'nothing' for c
        d = New derived_class
        CopyProperties(d, b)
        d.dval = 20
        Console.WriteLine(b.bval)
        Console.WriteLine(d.bval)
        Console.WriteLine(d.dval)
        Console.ReadLine()
    End Sub
End Module

Of course this isn't really casting. It's creating a new derived object and copying the properties from the parent, leaving the child properties blank. That's all I needed to do and it sounds like its all you need to do. Note it only copies properties, not members (public variables) in the class (but you could extend it to do that if you are for shame exposing public members).

当然这不是真正的铸造。它正在创建一个新的派生对象并从父项复制属性,将子属性保留为空。这就是我需要做的所有事情,听起来就像你需要做的一切。请注意,它只复制属性,而不是类中的成员(公共变量)(但是如果你因为暴露公共成员而感到羞耻,你可以扩展它)。

Casting in general creates 2 variables pointing to the same object (mini tutorial here, please don't throw corner case exceptions at me). There are significant ramifications to this (exercise to the reader)!

一般来说,强制转换会创建两个指向同一对象的变量(这里的迷你教程,请不要向我抛出异常情况例外)。对此有重大影响(向读者练习)!

Of course I have to say why the languague doesn't let you go from base to derive instance, but does the other way. imagine a case where you can take an instance of a winforms textbox (derived) and store it in a variable of type Winforms control. Of course the 'control' can move the object around OK and you can deal with all the 'controll-y' things about the textbox (e.g., top, left, .text properties). The textbox specific stuff (e.g., .multiline) can't be seen without casting the 'control' type variable pointing to the textbox in memory, but it's still there in memory.

当然,我必须说明为什么语言不会让你从基地出发来推导实例,而是以另一种方式。想象一下你可以获取winforms文本框(派生)的实例并将其存储在Winforms控件类型的变量中的情况。当然,'控件'可以将对象移动到OK,你可以处理关于文本框的所有'controll-y'事物(例如,top,left,.text属性)。如果没有将指向内存中文本框的'control'类型变量强制转换,则无法看到特定于文本框的内容(例如.multiline),但它仍然存在于内存中。

Now imagine, you have a control, and you want to case a variable of type textbox to it. The Control in memory is missing 'multiline' and other textboxy things. If you try to reference them, the control won't magically grow a multiline property! The property (look at it like a member variable here, that actually stores a value - because there is on in the textbox instance's memory) must exist. Since you are casting, remember, it has to be the same object you're pointing to. Hence it is not a language restriction, it is philosophically impossible to case in such a manner.

现在想象一下,你有一个控件,并且你想要一个类型为textbox的变量。内存中的控件缺少“多线”和其他文本内容。如果您尝试引用它们,控件将不会神奇地增长多行属性!属性(在这里看它就像一个成员变量,实际存储一个值 - 因为文本框实例的内存中存在)必须存在。因为你正在施法,记住,它必须是你指向的同一个物体。因此,它不是一种语言限制,在这种情况下在哲学上是不可能的。

#7


I have seen most of the people saying explicit parent to child casting is not possible, that actually is not true. Let's take a revised start and try proving it by examples.

我已经看到大多数人都说不明确父母对孩子的投射是不可能的,实际上并非如此。让我们采取修改后的开始,并尝试通过示例证明它。

As we know in .net all castings have two broad categories.

正如我们在.net中所知,所有铸件都有两大类。

  1. For Value type
  2. 对于值类型

  3. For Reference type (in your case its reference type)
  4. 对于引用类型(在您的情况下为其引用类型)

Reference type has further three main situational cases in which any scenario can lie.

参考类型还有三个主要情境案例,其中任何情景都可能存在。

Child to Parent (Implicit casting - Always successful)

Case 1. Child to any direct or indirect parent

案例1.任何直接或间接父母的孩子

Employee e = new Employee();
Person p = (Person)e; //Allowed

Parent to Child (Explicit casting - Can be successful)

Case 2. Parent variable holding parent object (Not allowed)

案例2.父变量持有父对象(不允许)

Person p = new Person();  // p is true Person object
Employee e = (Employee)p; //Runtime err : InvalidCastException <-------- Yours issue

Case 3. Parent variable holding child object (Always Successful)

案例3.包含子对象的父变量(始终成功)

Note: Because objects has polymorphic nature, it is possible for a variable of a parent class type to hold a child type.

注意:由于对象具有多态性,因此父类类型的变量可以保存子类型。

Person p = new Employee(); // p actually is Employee
Employee e = (Employee)p; // Casting allowed

Conclusion : After reading above all, hope it will make sense now like how parent to child conversion is possible(Case 3).

结论:首先阅读之后,希望它现在有意义,如父母到孩子的转换是可能的(案例3)。

Answer To The Question :

Your answer is in case 2.Where you can see such casting is not allowed by OOP and you are trying to violate one of OOP's basic rule.So always choose safe path.

你的答案是2。你可以看到OOP不允许这样的投射而你试图违反OOP的基本规则之一。所以总是选择安全路径。

Further more, to avoid such exceptional situations .net has recommended using is/as operators those will help you to take informed decisions and provide safe casting.

此外,为了避免这种特殊情况,.net建议使用is / as运算符来帮助您做出明智的决策并提供安全的投射。

#8


The instance of the object should be created using the child class's type, you can't cast a parent type instance to a child type

应使用子类的类型创建对象的实例,不能将父类型实例强制转换为子类型

#9


As of C# 7.0, you can use the is keyword to do this :

从C#7.0开始,您可以使用is关键字来执行此操作:

With those class defined :

定义了这些类:

class Base { /* Define base class */ }
class Derived : Base { /* Define derived class */ }

You can then do somehting like :

然后你可以做一些像:

void Funtion(Base b)
{
    if (b is Derived d)
    {
        /* Do something with d which is now a variable of type Derived */
    }
}

Which would be equivalent to :

这相当于:

void Funtion(Base b)
{
    Defined d;
    if (b is Derived)
    {
        d = (Defined)b;
        /* Do something with d */
    }
}

You could now call :

你现在可以打电话:

Function(new Derived()); // Will execute code defined in if

As well as

以及

Function(new Base()); // Won't execute code defined in if

That way you can be sure that your downcast will be valid and won't throw an exception !

这样你就可以确定你的垂头丧气有效并且不会抛出异常!

#10


To cast, the actual object must be of a Type equal to or derived from the Type you are attempting to cast to...

要进行强制转换,实际对象必须是类型等于或派生自您尝试强制转换的类型...

or, to state it in the opposite way, the Type you are trying to cast it to must be the same as, or a base class of, the actual type of the object.

或者,以相反的方式说明,您尝试将其强制转换为的类型必须与对象的实际类型相同或基类。

if your actual object is of type Baseclass, then you can't cast it to a derived class Type...

如果您的实际对象是Baseclass类型,那么您不能将它强制转换为派生类Type ...

#11


A variation on the serialization approach for those using ServiceStack:

使用ServiceStack的序列化方法的变体:

var child = baseObject.ConvertTo<ChildType>();

or the more verbose:

或者更详细:

var child = baseObject.ToJson().FromJson<ChildType>();

ServiceStack's serialization might be super fast and all, but clearly, this is not a solution for massive conversions in low-latency transfers, nor for highly complex types. That's likely obvious to anyone using ServiceStack, but thought I'd clarify in anticipation of comments.

ServiceStack的序列化速度可能超快,但很明显,这不是低延迟传输中大规模转换的解决方案,也不是高度复杂类型的解决方案。对于任何使用ServiceStack的人来说,这可能是显而易见的,但我认为我会在预期评论时澄清。

#12


As for me it was enough to copy all property fields from the base class to the parent like this:

至于我,将所有属性字段从基类复制到父类就足够了,如下所示:

using System.Reflection;

public static ChildClass Clone(BaseClass b)
{
    ChildClass p = new ChildClass(...);

    // Getting properties of base class

    PropertyInfo[] properties = typeof(BaseClass).GetProperties();

    // Copy all properties to parent class

    foreach (PropertyInfo pi in properties)
    {
        if (pi.CanWrite)
            pi.SetValue(p, pi.GetValue(b, null), null);
    }

    return p;
}

An universal solution for any object can be found here

可以在此处找到任何对象的通用解决方案

#1


You can't cast a mammal into a dog - it might be a cat.

你不能把哺乳动物变成狗 - 它可能是一只猫。

You can't cast a food into a sandwich - it might be a cheeseburger.

你不能把食物扔进三明治 - 它可能是一个芝士汉堡。

You can't cast a car into a Ferrari - it might be a Honda, or more specifically, You can't cast a Ferrari 360 Modena to a Ferrari 360 Challange Stradale - there are differnt parts, even though they are both Ferrari 360s.

你不能把汽车变成法拉利 - 它可能是本田,或者更具体地说,你不能将法拉利360摩德纳投射到法拉利360 Challange Stradale--虽然它们都是法拉利360,但它们有不同的部分。

#2


A simple way to downcast in C# is to serialize the parent and then deserialize it into the child.

在C#中向下转换的一种简单方法是序列化父对象,然后将其反序列化为子对象。

 var serializedParent = JsonConvert.SerializeObject(parentInstance); 
 Child c  = JsonConvert.DeserializeObject<Child>(serializedParent);

I have a simple console app that casts animal into dog, using the above two lines of code over here

我有一个简单的控制台应用程序,使用上面两行代码将动物投入狗

#3


The instance that your base class reference is referring to is not an instance of your child class. There's nothing wrong.

基类引用所引用的实例不是子类的实例。没有错。

More specifically:

Base derivedInstance = new Derived();
Base baseInstance = new Base();

Derived good = (Derived)derivedInstance; // OK
Derived fail = (Derived)baseInstance; // Throws InvalidCastException

For the cast to be successful, the instance that you're downcasting must be an instance of the class that you're downcasting to (or at least, the class you're downcasting to must be within the instance's class hierarchy), otherwise the cast will fail.

为了使转换成功,您正在向下转换的实例必须是您正在向下转换的类的实例(或者至少,您要向下转换的类必须在实例的类层次结构中),否则演员会失败。

#4


There are some cases when such a cast would make sense.
I my case, I was receiving a BASE class over the network, and I needed more features to it. So deriving it to handle it on my side with all the bells and whistles I wanted, and casting the received BASE class into the DERIVED one was simply not an option (Throws InvalidCastException of Course)

在某些情况下,这样的演员会有意义。我的情况是,我通过网络接收了一个BASE课程,我需要更多的功能。因此得出它来处理它我所需要的所有铃声和口哨,并将收到的BASE类转换为DERIVED一个根本不是一个选项(抛出InvalidCastException of Course)

One practical think-out-of-the-box SOLUTION was to declare an EXTENSION Helper class that was NOT inheriting BASE class actually, but INCLUDING IT as a member.

一个实用的开箱即用的解决方案是声明一个EXTENSION Helper类,它实际上并没有继承BASE类,而是将它作为成员包含在内。

public class BaseExtension
{
   Base baseInstance;

   public FakeDerived(Base b)
   {
      baseInstance = b;
   }

   //Helper methods and extensions to Base class added here
}

If you have loose coupling and just need a couple of extra features to base class without REALLY having an absolute need of derivation, that could be a quick and simple workaround.

如果你有松散的耦合,只需要一些额外的功能来基类而不必绝对需要派生,那么这可能是一个快速而简单的解决方法。

#5


That would violate object oriented principles. I'd say an elegant solution here and elsewhere in the project is using a object mapping framework like AutoMapper to configure a projection.

这将违反面向对象的原则。我想在这里和项目的其他地方使用像AutoMapper这样的对象映射框架来配置投影。

Here's a slighty more complex configuration than is neccessary but is flexible enough for most cases:

这是一个比必要的更复杂的配置,但对于大多数情况来说足够灵活:

public class BaseToChildMappingProfile : Profile
{
    public override string ProfileName
    {
        get { return "BaseToChildMappingProfile"; }
    }

    protected override void Configure()
    {
        Mapper.CreateMap<BaseClass, ChildClassOne>();
        Mapper.CreateMap<BaseClass, ChildClassTwo>();
    }
}


public class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(x =>
        {
            x.AddProfile<BaseToChildMappingProfile>();
        });
    }
}

When application starts call AutoMapperConfiguration.Configure() and then you can project like this:

当应用程序启动时调用AutoMapperConfiguration.Configure()然后你可以这样投影:

ChildClassOne child = Mapper.Map<BaseClass, ChildClassOne>(baseClass);

Properties are mapped by convention so if the class is inherited the property names are exactly the same and mapping is configured automatically. You can add additional properties by tweaking the configuration. See the documentation .

属性按约定映射,因此如果继承该类,则属性名称完全相同,并自动配置映射。您可以通过调整配置来添加其他属性。请参阅文档。

#6


Paul, you didn't ask 'Can I do it' - I am assuming you want to know how to do it!

保罗,你没有问'我能做到吗' - 我假设你想知道怎么做!

We had to do this on a project - there are many of classes we set up in a generic fashion just once, then initialize properties specific to derived classes. I use VB so my sample is in VB (tough noogies), but I stole the VB sample from this site which also has a better C# version:

我们必须在一个项目上执行此操作 - 我们只以通用方式设置了许多类,然后初始化特定于派生类的属性。我使用VB所以我的样本是在VB(艰难的noogies),但我偷了这个网站的VB样本,它也有一个更好的C#版本:

http://www.eggheadcafe.com/tutorials/aspnet/a4264125-fcb0-4757-9d78-ff541dfbcb56/net-reflection--copy-cl.aspx

Sample code:

Imports System
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Text
Imports System.Diagnostics

Module ClassUtils

    Public Sub CopyProperties(ByVal dst As Object, ByVal src As Object)
        Dim srcProperties() As PropertyInfo = src.GetType.GetProperties
        Dim dstType = dst.GetType

        If srcProperties Is Nothing Or dstType.GetProperties Is Nothing Then
            Return
        End If

        For Each srcProperty As PropertyInfo In srcProperties
            Dim dstProperty As PropertyInfo = dstType.GetProperty(srcProperty.Name)

            If dstProperty IsNot Nothing Then
                If dstProperty.PropertyType.IsAssignableFrom(srcProperty.PropertyType) = True Then
                    dstProperty.SetValue(dst, srcProperty.GetValue(src, Nothing), Nothing)
                End If
            End If
        Next
    End Sub
End Module


Module Module1
    Class base_class
        Dim _bval As Integer
        Public Property bval() As Integer
            Get
                Return _bval
            End Get
            Set(ByVal value As Integer)
                _bval = value
            End Set
        End Property
    End Class
    Class derived_class
        Inherits base_class
        Public _dval As Integer
        Public Property dval() As Integer
            Get
                Return _dval
            End Get
            Set(ByVal value As Integer)
                _dval = value
            End Set
        End Property
    End Class
    Sub Main()
        ' NARROWING CONVERSION TEST
        Dim b As New base_class
        b.bval = 10
        Dim d As derived_class
        'd = CType(b, derived_class) ' invalidcast exception 
        'd = DirectCast(b, derived_class) ' invalidcast exception
        'd = TryCast(b, derived_class) ' returns 'nothing' for c
        d = New derived_class
        CopyProperties(d, b)
        d.dval = 20
        Console.WriteLine(b.bval)
        Console.WriteLine(d.bval)
        Console.WriteLine(d.dval)
        Console.ReadLine()
    End Sub
End Module

Of course this isn't really casting. It's creating a new derived object and copying the properties from the parent, leaving the child properties blank. That's all I needed to do and it sounds like its all you need to do. Note it only copies properties, not members (public variables) in the class (but you could extend it to do that if you are for shame exposing public members).

当然这不是真正的铸造。它正在创建一个新的派生对象并从父项复制属性,将子属性保留为空。这就是我需要做的所有事情,听起来就像你需要做的一切。请注意,它只复制属性,而不是类中的成员(公共变量)(但是如果你因为暴露公共成员而感到羞耻,你可以扩展它)。

Casting in general creates 2 variables pointing to the same object (mini tutorial here, please don't throw corner case exceptions at me). There are significant ramifications to this (exercise to the reader)!

一般来说,强制转换会创建两个指向同一对象的变量(这里的迷你教程,请不要向我抛出异常情况例外)。对此有重大影响(向读者练习)!

Of course I have to say why the languague doesn't let you go from base to derive instance, but does the other way. imagine a case where you can take an instance of a winforms textbox (derived) and store it in a variable of type Winforms control. Of course the 'control' can move the object around OK and you can deal with all the 'controll-y' things about the textbox (e.g., top, left, .text properties). The textbox specific stuff (e.g., .multiline) can't be seen without casting the 'control' type variable pointing to the textbox in memory, but it's still there in memory.

当然,我必须说明为什么语言不会让你从基地出发来推导实例,而是以另一种方式。想象一下你可以获取winforms文本框(派生)的实例并将其存储在Winforms控件类型的变量中的情况。当然,'控件'可以将对象移动到OK,你可以处理关于文本框的所有'controll-y'事物(例如,top,left,.text属性)。如果没有将指向内存中文本框的'control'类型变量强制转换,则无法看到特定于文本框的内容(例如.multiline),但它仍然存在于内存中。

Now imagine, you have a control, and you want to case a variable of type textbox to it. The Control in memory is missing 'multiline' and other textboxy things. If you try to reference them, the control won't magically grow a multiline property! The property (look at it like a member variable here, that actually stores a value - because there is on in the textbox instance's memory) must exist. Since you are casting, remember, it has to be the same object you're pointing to. Hence it is not a language restriction, it is philosophically impossible to case in such a manner.

现在想象一下,你有一个控件,并且你想要一个类型为textbox的变量。内存中的控件缺少“多线”和其他文本内容。如果您尝试引用它们,控件将不会神奇地增长多行属性!属性(在这里看它就像一个成员变量,实际存储一个值 - 因为文本框实例的内存中存在)必须存在。因为你正在施法,记住,它必须是你指向的同一个物体。因此,它不是一种语言限制,在这种情况下在哲学上是不可能的。

#7


I have seen most of the people saying explicit parent to child casting is not possible, that actually is not true. Let's take a revised start and try proving it by examples.

我已经看到大多数人都说不明确父母对孩子的投射是不可能的,实际上并非如此。让我们采取修改后的开始,并尝试通过示例证明它。

As we know in .net all castings have two broad categories.

正如我们在.net中所知,所有铸件都有两大类。

  1. For Value type
  2. 对于值类型

  3. For Reference type (in your case its reference type)
  4. 对于引用类型(在您的情况下为其引用类型)

Reference type has further three main situational cases in which any scenario can lie.

参考类型还有三个主要情境案例,其中任何情景都可能存在。

Child to Parent (Implicit casting - Always successful)

Case 1. Child to any direct or indirect parent

案例1.任何直接或间接父母的孩子

Employee e = new Employee();
Person p = (Person)e; //Allowed

Parent to Child (Explicit casting - Can be successful)

Case 2. Parent variable holding parent object (Not allowed)

案例2.父变量持有父对象(不允许)

Person p = new Person();  // p is true Person object
Employee e = (Employee)p; //Runtime err : InvalidCastException <-------- Yours issue

Case 3. Parent variable holding child object (Always Successful)

案例3.包含子对象的父变量(始终成功)

Note: Because objects has polymorphic nature, it is possible for a variable of a parent class type to hold a child type.

注意:由于对象具有多态性,因此父类类型的变量可以保存子类型。

Person p = new Employee(); // p actually is Employee
Employee e = (Employee)p; // Casting allowed

Conclusion : After reading above all, hope it will make sense now like how parent to child conversion is possible(Case 3).

结论:首先阅读之后,希望它现在有意义,如父母到孩子的转换是可能的(案例3)。

Answer To The Question :

Your answer is in case 2.Where you can see such casting is not allowed by OOP and you are trying to violate one of OOP's basic rule.So always choose safe path.

你的答案是2。你可以看到OOP不允许这样的投射而你试图违反OOP的基本规则之一。所以总是选择安全路径。

Further more, to avoid such exceptional situations .net has recommended using is/as operators those will help you to take informed decisions and provide safe casting.

此外,为了避免这种特殊情况,.net建议使用is / as运算符来帮助您做出明智的决策并提供安全的投射。

#8


The instance of the object should be created using the child class's type, you can't cast a parent type instance to a child type

应使用子类的类型创建对象的实例,不能将父类型实例强制转换为子类型

#9


As of C# 7.0, you can use the is keyword to do this :

从C#7.0开始,您可以使用is关键字来执行此操作:

With those class defined :

定义了这些类:

class Base { /* Define base class */ }
class Derived : Base { /* Define derived class */ }

You can then do somehting like :

然后你可以做一些像:

void Funtion(Base b)
{
    if (b is Derived d)
    {
        /* Do something with d which is now a variable of type Derived */
    }
}

Which would be equivalent to :

这相当于:

void Funtion(Base b)
{
    Defined d;
    if (b is Derived)
    {
        d = (Defined)b;
        /* Do something with d */
    }
}

You could now call :

你现在可以打电话:

Function(new Derived()); // Will execute code defined in if

As well as

以及

Function(new Base()); // Won't execute code defined in if

That way you can be sure that your downcast will be valid and won't throw an exception !

这样你就可以确定你的垂头丧气有效并且不会抛出异常!

#10


To cast, the actual object must be of a Type equal to or derived from the Type you are attempting to cast to...

要进行强制转换,实际对象必须是类型等于或派生自您尝试强制转换的类型...

or, to state it in the opposite way, the Type you are trying to cast it to must be the same as, or a base class of, the actual type of the object.

或者,以相反的方式说明,您尝试将其强制转换为的类型必须与对象的实际类型相同或基类。

if your actual object is of type Baseclass, then you can't cast it to a derived class Type...

如果您的实际对象是Baseclass类型,那么您不能将它强制转换为派生类Type ...

#11


A variation on the serialization approach for those using ServiceStack:

使用ServiceStack的序列化方法的变体:

var child = baseObject.ConvertTo<ChildType>();

or the more verbose:

或者更详细:

var child = baseObject.ToJson().FromJson<ChildType>();

ServiceStack's serialization might be super fast and all, but clearly, this is not a solution for massive conversions in low-latency transfers, nor for highly complex types. That's likely obvious to anyone using ServiceStack, but thought I'd clarify in anticipation of comments.

ServiceStack的序列化速度可能超快,但很明显,这不是低延迟传输中大规模转换的解决方案,也不是高度复杂类型的解决方案。对于任何使用ServiceStack的人来说,这可能是显而易见的,但我认为我会在预期评论时澄清。

#12


As for me it was enough to copy all property fields from the base class to the parent like this:

至于我,将所有属性字段从基类复制到父类就足够了,如下所示:

using System.Reflection;

public static ChildClass Clone(BaseClass b)
{
    ChildClass p = new ChildClass(...);

    // Getting properties of base class

    PropertyInfo[] properties = typeof(BaseClass).GetProperties();

    // Copy all properties to parent class

    foreach (PropertyInfo pi in properties)
    {
        if (pi.CanWrite)
            pi.SetValue(p, pi.GetValue(b, null), null);
    }

    return p;
}

An universal solution for any object can be found here

可以在此处找到任何对象的通用解决方案