将对象强制转换为派生类中的对象
本文关键字:对象 派生 转换 | 更新日期: 2023-09-27 18:30:37
我有一个工作正常的类Record
:
public class Record
{
protected string table;
protected string idcolumn;
public Record(string _table, string _idcol, int _id)
{
table = _table;
idcolumn = _idcol;
Id = _id;
}
}
我还有一个派生自Record
的类Order
,它实现了额外的方法,仅适用于某种类型的记录:
class Order : Record
{
public void Start()
{
}
}
在我的应用程序中,我有一个 Record
类型的对象theRecord
,我想将其转换为 Order
,以便我可以对其调用 Start
方法。
我试着投掷它:
Order r = (Order)theRecord;
但这抛出了一个InvalidCastException
.
我想我可以为Order
创建一个新的构造函数,它需要一个Record
,但我已经有了这个对象(它是通过从数据库中获取记录来构建的)。
我怎样才能正确实现这一点?
如果你得到一个InvalidCastException
那么theRecord
就不是Order
,你不能投射它。 仅当它创建为 Order
或 Order
的子类时,才能强制转换它。
我的猜测是,无论从数据库中获取数据,当它可以创建Order
(并将其作为Record
返回)时,都会创建一个Record
。 像这样:
public Record Fetch(int id)
{
// ... get data from db
Record rec;
if(data.Type = "Order")
rec = new Order();
else
rec = new Record();
return rec;
}
正如我在评论中所说
你可以将狗投射到动物,但不能将动物投到狗(除非该动物是狗)。更清楚所有的狗都是动物,但不是所有的动物都是狗
Record record = new Record();
Order order = (Order)record;//wont work since record is some record not an Order
要让它工作,你必须做这样的事情
Record record = new Order();
然后你可以像这样投射它
Order order = (Order)record;//works since record is Order
您必须转换为新对象,而不是强制转换它。若要执行此操作而不一次编写一个属性的映射代码,最简单的方法是序列化Record
对象,然后将其反序列化为Order
。你可以使用任何你喜欢的序列化技术(XmlSerializer
、JavaScriptSerializer
、JSON.NET 等)。
这假设所有数据都可以在公共属性中使用普通 getter/setter 访问(在您的示例中没有,但您应该这样做)。如果你不想这样做,你可以使用反射来循环遍历Record
的字段,从那里获取值,并使用反射来填充Order
的字段。
在实际尝试强制转换之前,您可以使用 is
和 as
运算符来确保某些内容属于某种类型,如下所示:
Record objectToHoldCastedObject;
if(theRecord is Order)
{
objectToHoldCastedObject = theRecord as Order;
}
is
将检查对象是该确切类型还是继承链的一部分。
as
将尝试将对象强制转换为类型,如果不能,则返回 null 而不是异常。
注意:as
仅适用于引用类型,不适用于值类型;而is
将同时适用于引用类型和值类型。因此,例如,您可以is
整数,但不能as
整数。