簡體   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