C# 是否可以使用显式类型转换将基类对象分配给派生类引用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/729527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:51:50  来源:igfitidea点击:

Is it possible to assign a base class object to a derived class reference with an explicit typecast?

c#explicitderived-classcastingbase-class

提问by Maddy.Shik

Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.

是否可以在 C# 中使用显式类型转换将基类对象分配给派生类引用?

I have tried it and it creates a run-time error.

我试过了,它会产生一个运行时错误。

采纳答案by Jon Skeet

No. A reference to a derived class must actually refer to an instance of the derived class (or null). Otherwise how would you expect it to behave?

否。对派生类的引用必须实际引用派生类的实例(或 null)。否则你会如何期望它的行为?

For example:

例如:

object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?

If you want to be able to convert an instance of the base type to the derived type, I suggest you write a method to create an appropriate derived type instance. Or look at your inheritance tree again and try to redesign so that you don't need to do this in the first place.

如果您希望能够将基类型的实例转换为派生类型,我建议您编写一个方法来创建适当的派生类型实例。或者再次查看您的继承树并尝试重新设计,以便您不需要首先执行此操作。

回答by ybo

No it is not possible, hence your runtime error.

不,这是不可能的,因此您的运行时错误。

But you can assign an instance of a derived class to a variable of base class type.

但是您可以将派生类的实例分配给基类类型的变量。

回答by Andy

Expanding on @ybo's answer - it isn't possible because the instance you have of the base class isn't actually an instance of the derived class. It only knows about the members of the base class, and doesn't know anything about those of the derived class.

扩展@ybo 的答案 - 这是不可能的,因为您拥有的基类实例实际上不是派生类的实例。它只知道基类的成员,对派生类的成员一无所知。

The reason that you can cast an instance of the derived class to an instance of the base class is because the derived class actually already is an instance of the base class, since it has those members already. The opposite cannot be said.

您可以将派生类的实例转换为基类的实例的原因是,派生类实际上已经是基类的实例,因为它已经具有这些成员。不能说相反。

回答by Marc Gravell

You can cast a variablethat is typed as the base-class to the type of a derived class; however, by necessity this will do a runtime check, to see if the actual object involved is of the correct type.

您可以将类型为基类的变量强制转换为派生类的类型;然而,必要时这将进行运行时检查,以查看所涉及的实际对象是否属于正确类型。

Once created, the typeof an object cannot be changed (not least, it might not be the same size). You can, however, convertan instance, creating a newinstance of the second type - but you need to write the conversion code manually.

一旦创建,对象的类型就不能改变(尤其是,它的大小可能不同)。但是,您可以转换实例,创建第二种类型的实例 - 但您需要手动编写转换代码。

回答by Aaron Powell

No, see this question which I asked - Upcasting in .NET using generics

不,请看我问的这个问题 - Upcasting in .NET using generics

The best way is to make a default constructor on the class, construct and then call an Initialisemethod

最好的方法是在类上创建一个默认构造函数,构造然后调用一个Initialise方法

回答by Michael Klement

No, that's not possible since assigning it to a derived class reference would be like saying "Base class is a fully capable substitute for derived class, it can do everything the derived class can do", which is not true since derived classes in general offer more functionality than their base class (at least, that's the idea behind inheritance).

不,这是不可能的,因为将它分配给派生类引用就像说“基类是派生类的完全替代品,它可以做派生类可以做的一切”,这是不正确的,因为派生类通常提供比它们的基类更多的功能(至少,这是继承背后的想法)。

You could write a constructor in the derived class taking a base class object as parameter, copying the values.

您可以在派生类中编写一个构造函数,将基类对象作为参数,复制值。

Something like this:

像这样的东西:

public class Base {
    public int Data;

    public void DoStuff() {
        // Do stuff with data
    }
}

public class Derived : Base {
    public int OtherData;

    public Derived(Base b) {
        this.Data = b.Data;
        OtherData = 0; // default value
    }

    public void DoOtherStuff() {
        // Do some other stuff
    }
}

In that case you would copy the base object and get a fully functional derived class object with default values for derived members. This way you can also avoid the problem pointed out by Jon Skeet:

在这种情况下,您将复制基对象并获得一个具有派生成员默认值的全功能派生类对象。这样你也可以避免 Jon Skeet 指出的问题:

Base b = new Base();//base class
Derived d = new Derived();//derived class

b.DoStuff();    // OK
d.DoStuff();    // Also OK
b.DoOtherStuff();    // Won't work!
d.DoOtherStuff();    // OK

d = new Derived(b);  // Copy construct a Derived with values of b
d.DoOtherStuff();    // Now works!

回答by Mahmoodvcs

As everyone here said, that's not possible directly.

正如这里的每个人所说,这不是直接可能的。

The method I prefer and is rather clean, is to use an Object Mapper like AutoMapper.

我更喜欢并且相当干净的方法是使用像AutoMapper这样的对象映射器。

It will do the task of copying properties from one instance to another (Not necessarily the same type) automatically.

它将自动完成将属性从一个实例复制到另一个实例(不一定是相同类型)的任务。

回答by Ark-kun

Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.

是否可以在 C# 中使用显式类型转换将基类对象分配给派生类引用?

Not only explicit, but also implicit conversions are possible.

不仅可以进行显式转换,还可以进行隐式转换。

C# language doesn't permit such conversion operators, but you can still write them using pure C# and they work. Note that the class which defines the implicit conversion operator (Derived) and the class which uses the operator (Program) must be defined in separate assemblies (e.g. the Derivedclass is in a library.dllwhich is referenced by program.execontaining the Programclass).

C# 语言不允许这样的转换运算符,但您仍然可以使用纯 C# 编写它们并且它们可以工作。请注意,定义隐式转换运算符 ( Derived) 的类和使用运算符 ( Program) 的类必须在单独的程序集中定义(例如,Derived类位于library.dll通过program.exe包含Program类引用的 a中)。

//In library.dll:
public class Base { }

public class Derived {
    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Implicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }

    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Explicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }
}

//In program.exe:
class Program {
    static void Main(string[] args) {
        Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
    }
}

When you reference the library using the Project Reference in Visual Studio, VS shows squiggles when you use the implicit conversion, but it compiles just fine. If you just reference the library.dll, there are no squiggles.

当您使用 Visual Studio 中的项目引用引用库时,VS 会在您使用隐式转换时显示波浪线,但它编译得很好。如果您只引用library.dll,则没有波浪线。

回答by Markus Knappen Johansson

I had this problem and solved it by adding a method that takes a type parameter and converts the current object into that type.

我遇到了这个问题,并通过添加一个接受类型参数并将当前对象转换为该类型的方法来解决它。

public TA As<TA>() where TA : Base
{
    var type = typeof (TA);
    var instance = Activator.CreateInstance(type);

     PropertyInfo[] properties = type.GetProperties();
     foreach (var property in properties)
     {
         property.SetValue(instance, property.GetValue(this, null), null);
     }

     return (TA)instance;
}

That means that you can use it in you code like this:

这意味着您可以在代码中使用它,如下所示:

var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1

回答by Rohit Dodle

No, it is not possible.

不,这是不可能的。

Consider a scenario where an ACBus is a derived class of base class Bus. ACBus has features like TurnOnAC and TurnOffAC which operate on a field named ACState. TurnOnAC sets ACState to on and TurnOffAC sets ACState to off. If you try to use TurnOnAC and TurnOffAC features on Bus, it makes no sense.

考虑一个场景,其中 ACBus 是基类 Bus 的派生类。ACBus 具有 TurnOnAC 和 TurnOffAC 等功能,它们在名为 ACState 的字段上运行。TurnOnAC 将 ACState 设置为 on,TurnOffAC 将 ACState 设置为 off。如果您尝试在 Bus 上使用 TurnOnAC 和 TurnOffAC 功能,这是没有意义的。