C# 无法将基类(数据协定)强制转换为派生类
我正在MVC控制器操作中创建SearchCriteria实例,并尝试 将其转换为CitySearchCriteriaC# 无法将基类(数据协定)强制转换为派生类,c#,oop,casting,datacontract,derived-class,C#,Oop,Casting,Datacontract,Derived Class,我正在MVC控制器操作中创建SearchCriteria实例,并尝试 将其转换为CitySearchCriteria [DataContract] public class SearchCriteria { [DataMember] public string CountryID { get; set; } } [DataContract] public class CitySearchCriteria: SearchCriteria { [DataMember
[DataContract]
public class SearchCriteria
{
[DataMember]
public string CountryID { get; set; }
}
[DataContract]
public class CitySearchCriteria: SearchCriteria
{
[DataMember]
public string CityID { get; set; }
}
上述语句后面的“citySearchCriteria”对象显示空值。我希望它同时显示属性,CountryID和CityID,其中CountryID已填充,CityID为空。。。但它正在将对象设置为NULL
这里的解决方案是什么?DataContract与此有关吗
注释建议,不能将基转换为派生:
但事实上,在我看来,我已经成功地做到了这一点,只是在控制器操作中不起作用:
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.CountryID = "1";
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;
这是成功的转换,那么为什么类似的东西不能在控制器操作中工作呢?您不能以这种方式强制转换 如果执行
new
操作,将创建一个特定大小的新内存对象。在您的例子中,new SearchCriteria()
创建一个新的内存对象,其大小足以容纳一个字符串,不能多,也不能少
在最后一行中,您尝试将searchCriteria作为CitySearchCriteria
中的对象强制转换为更大的类型CitySearchCriteria
。但这是不可能做到的。您正在尝试将一个包含1个字符串的内存对象“转换”为一个包含2个字符串的内存对象。但强制转换不会转换新的内存对象。新字符串的值是多少?它只是在水下查看您的引用searchCriteria
是否已包含类型为CitySearchCriteria
的对象。在您的情况下:它不会(对象类型为SearchCriteria
)并返回null
所以。。。下一个示例确实有效(因为已经创建了CitySearchCriteria)。这也是您的解决方案:
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;
这不起作用(因为还没有创建CitySearchCriteria)。这就是你的情况:
SearchCriteria searchCriteria = new CitySearchCriteria();
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;
这与下一个示例相同。此确实有效(因为已创建搜索条件): 而这不是(因为还没有创建搜索条件)::
作为记录:我将始终使用直接强制转换,而不是使用
as
的强制转换,除非您希望明确测试对象是否属于该类型。您可以创建CitySearchCriteria,并将其强制转换为SearchCriteria。这样您只能看到CountryId。稍后,您可以将其转换回CitySearchCriteria,并查看CountryId和CityId
这与DataContract无关。您的解决方案是创建CitySearchCriteria并将其转换为SearchCriteria(如果您需要)。每个人都已经(正确地)告诉过您,您无法从基转换为派生,但在我看来,您仍然不明白为什么这一行可以在您的另一段代码中工作:
object o = new object();
SearchCriteria searchCriteria = o as SearchCriteria;
我认为您对实例的“类型”有点困惑。您没有发布模型的定义,但我认为您有如下内容:
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;
这并不意味着SearchCriteria总是包含SearchCriteria的实例,只是它包含可以转换为SearchCriteria的类型的实例。在您的情况下,它可以包含SearchCriteria或CitySearchCriteria的实例。我想在您的代码中,您会发现如下内容:
public SearchCriteria SearchCriteria;
这就是让你的演员能够正确执行的原因。您可以看到,该实例实际上是一个CitySearchCriteria(而不仅仅是SearchCriteria的实例),在强制转换之前执行以下代码:
Model.SearchCriteria = new CitySearchCriteria();
为了更好地理解,您可以尝试在工作强制转换之前修改SearchCriteria中的值,如下所示,但发现强制转换不再工作:
MessageBox.Show(Model.SearchCriteria.GetType().FullName);
不能从基转换为派生。相反的情况是可能的。请参阅问题的最后两段再次检查Martin的答案(第一个示例)。它无法转换,因为根据他的实现,转换将无法从基类转换为派生类。相反是可能的。我想这正是我所说的。。。不是吗?还是我不明白你的意思?我课文中的哪个例子不正确?是的,第三个可以。对象可以包含任何类型。您可以将其强制转换为任何类型,只要它保持该类型。另一个例子是:
objecto=“Hello”;字符串s=o作为字符串为什么你认为它不起作用?我不是这个意思。他的问题的解决方案在哪里?解决方案是示例#1。我发现了两个类似的问题:问题是,我的视图需要一个“SearchCriteria”对象,因为它是从多个地方调用的,根据调用控制器和操作,可以有“CitySearchCriteria”、“StateSearchCriteria”等。此外,我已经在我的视图中成功地做到了这一点,比如CitySearchCriteria CitySearchCriteria=(CitySearchCriteria)Model.SearchCriteria;这很好,那么为什么控制器不采取行动呢?谢谢,是的,你是对的,我对此有很多困惑。这些细节已经澄清了这一点,我可以看出我在编码上的错误。谢谢
Model.SearchCriteria = new CitySearchCriteria();
MessageBox.Show(Model.SearchCriteria.GetType().FullName);
Model.SearchCriteria = new SearchCriteria();
MessageBox.Show(Model.SearchCriteria.GetType().FullName);
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;