无法将Base类(数据协定)强制转换为派生类

时间:2013-05-06 05:56:07

标签: c# oop casting datacontract derived-class

[DataContract]
public class SearchCriteria
{
    [DataMember]
    public string CountryID { get; set; }    
}

[DataContract]
public class CitySearchCriteria: SearchCriteria
{
    [DataMember]
    public string CityID { get; set; }
}

我正在我的MVC控制器操作中创建一个SearchCriteria实例,并尝试 将其转换为CitySearchCriteria。

SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.CountryID = "1";
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;

上述语句后的“citySearchCriteria”对象显示NULL值。我希望它显示属性,CountryID和CityID,其中CountryID已填充,CityID为空......但它将对象设置为NULL。

这里有什么解决方案? DataContract有什么用呢?

评论建议,你不能将基数转换为派生: 但实际上,我已经在我看来成功完成了这项工作,它只是在控制器操作中不起作用:

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

这是成功转换的,为什么类似的东西不能在控制器动作中工作呢?

3 个答案:

答案 0 :(得分:7)

你不能这样投!

如果执行new,则会创建一个特定大小的新内存对象。在你的情况下,new SearchCriteria()创建一个新的内存对象,其大小足以容纳一个字符串,仅此而已。

在最后一行中,您searchCriteria as CitySearchCriteria尝试将searchCriteria中的对象投射到更大的类型CitySearchCriteria。但它无法完成。您正在尝试将包含1个字符串的内存对象“转换”为可容纳2个字符串的内存对象。但是转换不会转换新的内存对象。新字符串的价值是多少?它只是在水下查看您的引用searchCriteria是否已包含CitySearchCriteria类型的对象。在您的情况下:它不是(对象的类型为SearchCriteria)并返回null

所以......下一个例子可以工作(因为已经创建了CitySearchCriteria)。这也是你的解决方案:

SearchCriteria searchCriteria = new CitySearchCriteria(); 
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;

无法正常工作(因为尚未创建CitySearchCriteria)。这是你的情况:

SearchCriteria searchCriteria = new SearchCriteria();
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;

与下一个例子相同。
可以正常工作(因为已经创建了SearchCriteria):

object o = new SearchCriteria();
SearchCriteria searchCriteria = o as SearchCriteria;

这样做(因为尚未创建SearchCriteria)::

object o = new object();
SearchCriteria searchCriteria = o as SearchCriteria;

对于记录:我总是使用直接强制转换,而不是使用as的强制转换,除非您要显式测试对象是否属于该类型。

答案 1 :(得分:5)

每个人都已经(并且正确地)告诉过你,你根本无法从Base转换为Derived,但在我看来,你仍然无法理解为什么这条线在你的代码的另一块中工作:< / p>

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

我认为你对实例的“类型”有点困惑。你没有发布模型的定义,但我认为你有这样的东西:

public SearchCriteria SearchCriteria;

这并不意味着SearchCriteria始终包含SearchCriteria的实例,而只是包含可以强制转换为SearchCriteria的类型实例。在您的情况下,它可以包含SearchCriteria或CitySearchCriteria的实例。我想在你的代码中的某个地方你会找到类似的东西:

Model.SearchCriteria = new CitySearchCriteria();

这是允许正确执行yor强制转换的原因。你可以看到实例确实是一个CitySearchCriteria(而不仅仅是SearchCriteria的一个实例)在演员表之前执行这段代码:

MessageBox.Show(Model.SearchCriteria.GetType().FullName;

为了更好地理解你可以尝试在工作演员之前修改SearchCriteria中的值,如下所示,只是为了发现演员阵容不再有效:

Model.SearchCriteria = new SearchCriteria();
MessageBox.Show(Model.SearchCriteria.GetType().FullName;
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

答案 2 :(得分:2)

您可以创建CitySearchCriteria,并将其投射到SearchCriteria。这样你只能看到CountryId。稍后,您可以将其强制转换回CitySearchCriteria,并查看CountryId和CityId。

这与DataContract无关。您的案例中的解决方案是创建CitySearchCriteria并将其投射到SearchCriteria(如果您需要)。