如何将接口转换为c#中的类型?
我有一个返回接口的属性。在调试期间,我可以中断返回的内容,虽然它是接口,但VisualStudio足够聪明,可以知道它实际上是什么派生类型。我想它是在使用反射或其他东西。我不确定。我的问题是,我是否可以在运行时获得相同的信息,以便创建适当类型的变量并按此方式转换接口?我的意思是:如何将接口转换为c#中的类型?,c#,.net,interface,casting,polymorphism,C#,.net,Interface,Casting,Polymorphism,我有一个返回接口的属性。在调试期间,我可以中断返回的内容,虽然它是接口,但VisualStudio足够聪明,可以知道它实际上是什么派生类型。我想它是在使用反射或其他东西。我不确定。我的问题是,我是否可以在运行时获得相同的信息,以便创建适当类型的变量并按此方式转换接口?我的意思是: IPreDisplay preDisplay = cb.PreDisplay; 如果preDisplay是一个RedPreDisplay,我希望能够编写代码 RedPreDisplay tmp = preDispla
IPreDisplay preDisplay = cb.PreDisplay;
如果preDisplay是一个RedPreDisplay,我希望能够编写代码
RedPreDisplay tmp = preDisplay as RedPreDisplay;
或者如果preDisplay是绿色preDisplay
GreenPreDisplay tmp = preDisplay as GreenPreDisplay;
等等。。。
如果可能的话,我希望避免一个混乱的switch语句,如果我可以使用泛型,那就太好了
如果您有任何建议或示例,请与我分享。根据您尝试执行的操作,您可能应该向接口添加操作方法/属性,这样您就不需要知道类型-即多态性 例如:
当你遇到需要这样做的情况时,这意味着你做错了什么。您需要备份并找出设计要求您这样做的原因。如果你发现自己被困在那里,我强烈建议你发布一个新的问题来获得设计方面的帮助——这里有很多聪明的人可以提供帮助 要直接回答您的问题,不-您不能在没有某种if/else或条件的情况下这样做,因为您必须显式使用静态类型。您可以使用反射来调用该方法,但由于您似乎需要调用接口不支持的东西(但某些对象支持),因此无论如何,您都需要编写每个静态类型的条件来调用该方法。直接对类型进行编码即可 编辑:根据评论中的讨论,最好的解决方案是为具有此其他属性或方法的类添加第二个接口。然后你可以做一个简单的检查:
IPreDisplay display = cb.PreDisplay;
IOtherInterface displayAsOther = display as IOtherInterface;
if(displayAsOther != null)
{
displayAsOther.OtherMethod();
}
使用接口的全部目的是执行代码不必知道确切的类型。尝试通过接口本身公开所有可能需要的信息,这样就不需要强制转换
可以理解,在极少数情况下,您可能仍然需要将接口转换为具体实现(特定类型)。如果您能提供更多的上下文,这可能会有所帮助。@Rex M绝对正确。问题在于代码和底层结构。一般来说,你不应该做你想做的事;仅针对接口编写代码 也就是说,如果您继承了坏代码并需要对其进行修补,那么
is
操作符可能会对您有所帮助。例如:
if(myInstance is MyBaseType)
{
MyBaseType myInstanceAsBaseType = myInstance as MyBaseType;
// handle MyBaseType specific issue
}
else if(myInstance is MyOtherBaseType)
{
MyOtherBaseType myInstanceAsOtherBaseType = myInstance as MyOtherBaseType;
// handle MyOtherBaseType specific issue.
}
泛型对您没有帮助,您也不能在switch语句中这样做。但它会让你的工作,虽然工作方式非常丑陋正如其他回答者指出的,你可能应该考虑为什么你的设计需要不同的逻辑,因为不同的类型不能被拉到一个接口中。 但是,假设有充分的理由,您只有几个选择:
void Foo()
{
dynamic preDisplay = cb.PreDisplay;
DoSomethingWith( preDisplay ); // runtime dispatch using dynamic runtime (DLR)
}
void DoSomethingWith( RedPreDisplay r ) { ... } // code specific to RefPreDisplay
void DoSomethingWith( GreenPreDisplay g ) { ... } // code specific to GreenPreDisplay
void DoSomethingWIth( IPreDisplay o ) { ... } // catch-all
你为什么要这么做?当您将接口转换为适当的类型时,当您想要使用它时,返回接口的目的难道不是丢失了吗?您的问题揭示了一些基本的混乱(或者您在语言上过于草率),没有任何东西可以“返回”接口,因为在运行时接口不存在。它将某个具体类型的对象“CAST”返回到接口。但是cast并没有改变对象,它只是改变了持有引用的变量的性质object@Charles布雷塔纳:不幸的是,你觉得有必要说明你刚才做了什么;太多人不理解对象实例和它所针对的类型之间的区别。我建议阅读Liskov替换原则:(所有派生类型都应该能够被视为基本类型):在C#4.0中,如果不使用switch/else,您可以在运行时使用dynamic关键字将类型分派给具有特定签名的方法。@LBushkin非常正确,但C#4.0尚未发布,因此不能合理地假设每个有4可能解决的问题的人都可以简单地切换到beta版本。即使是RTM,即使可以在C#4中实现,也可能不是一个好主意。即使在支持它的语言(如VBScript)中,我也从未使用过它。IPreDisplay在整个应用程序中都使用。一些实现它的对象没有接口不提供的属性。我认为我的最佳选择是创建一个新的接口,并用一小组对象实现它。也许这就是这里的解决办法。@Kettenbach这听起来确实是个好办法。接口的用途范围应尽可能有限,因此,如果您有一些对象实现的新功能子集,则该子集应为单独的接口。
void Foo()
{
dynamic preDisplay = cb.PreDisplay;
DoSomethingWith( preDisplay ); // runtime dispatch using dynamic runtime (DLR)
}
void DoSomethingWith( RedPreDisplay r ) { ... } // code specific to RefPreDisplay
void DoSomethingWith( GreenPreDisplay g ) { ... } // code specific to GreenPreDisplay
void DoSomethingWIth( IPreDisplay o ) { ... } // catch-all