繁体   English   中英

如何在c#中将接口转换为类型?

[英]How can I cast an Interface as its type in c#?

我有一个返回接口的属性。 在调试期间,我可以打破返回的内容,当它是界面时,Visual Studio足够聪明,可以知道它实际上是派生类型。 我假设它使用反射或其他东西。 我不确定。 我的问题是,我可以在运行时向我提供相同的信息,这样我就可以创建一个适当类型的变量并将接口转换为那样的接口吗? 这就是我的意思:

IPreDisplay preDisplay = cb.PreDisplay;

如果preDisplay是RedPreDisplay,我希望能够编码

RedPreDisplay tmp = preDisplay as RedPreDisplay;

或者如果preDisplay是GreenPreDisplay ......

GreenPreDisplay tmp = preDisplay as GreenPreDisplay;

等...如果可能的话,我想避免使用凌乱的switch语句,如果我可以使用非常棒的泛型。

如果您对我如何做到这一点有任何建议或示例,请分享。

当你遇到需要这样做的情况时,这意味着你做错了什么。 您需要备份并找出您的设计要求您执行此操作的原因。 如果您发现自己被困在那里,我强烈建议您发布一个新问题以获得设计方面的帮助 - 这里有很多聪明人可以提供帮助。

要直接回答你的问题,不 - 如果没有某种if / else或条件,你不能这样做,因为你必须明确静态类型。 您可以使用反射来调用该方法,但由于您似乎需要调用接口不支持的东西 - 但是某些对象会这样做 - 您需要编写一个每静态类型的条件来调用该方法。 只需直接编码类型。

编辑:根据评论中的讨论,最好的解决方案是向具有此其他属性或方法的类添加第二个接口。 然后你可以做一个简单的检查:

IPreDisplay display = cb.PreDisplay;
IOtherInterface displayAsOther = display as IOtherInterface;
if(displayAsOther != null)
{
    displayAsOther.OtherMethod();
}

使用接口的整个目的是执行代码不必知道确切的类型 尝试通过界面本身公开您可能需要的所有信息,因此您无需进行投射。

可以理解的是,您可能仍需要在极少数情况下将接口强制转换为具体实现(特定类型)。 如果您可以提供更多上下文,那可能会有所帮助。

根据你正在尝试做的事情,你应该向接口添加一个动作方法/属性,这样你就不需要知道类型 - 这是多态。

例如:

 IResultLiteEntity preDisplay = cb.PreDisplay;
 preDisplay.Render (); // New Render method on the interface...

@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语句的一部分。 但它会给你一些工作,虽然工作非常丑陋。

正如其他响应者所指出的那样,您可能应该考虑为什么您的设计需要针对不能被拉入接口的不同类型的不同逻辑。

但是,假设有充分的理由,您只有几个选择:

  1. 使用反射。 这通常是缓慢且容易出错的代码,当您的实现发生更改(即重命名方法等)时,代码也很脆弱。
  2. 使用if / else if / else模式根据类型的运行时检查进行分派。 这几乎是您在4.0之前版本的C#中唯一的其他选择。
  3. 如果您使用的是C#4.0,则可以使用将对象分配给动态var ,并在运行时分配给重载方法,该方法的签名因所支持的每种类型而异(请参见下面的示例)。

这是一个C#4.0动态调度示例:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM