2011-05-10 38 views
3

可能重複:
C# - Is there a better alternative than this to ‘switch on type’?如何在「可能」類型的對象之間切換?

我公司的遺留代碼有什麼如下

public override Uri GetUri(object obj) 
{ 
    if ((obj is Entry) || (obj is EntryComment)) 
    { 
     // 
    } 
    if (obj is Blog) 
    { 
     // 
    } 

    // if obj is blah blah blah 
} 

這種方法只是醜陋。我想重構它,但我不知道一種技術來遍歷obj可能的「可能」類型。

我該如何重構這個?

謝謝。

+0

我添加了region指令來演示代碼有多醜:-s – Vimvq1987 2011-05-10 08:36:07

+2

您可以將if語句塊內的代碼移入類型本身嗎?那樣你的方法就是:'return obj.Uri;'。 – 2011-05-10 08:36:50

+0

@Lasse V. Karlsen,+1爲您的評論。 – 2011-05-10 08:41:01

回答

4

您還可以使用接口

public interface IHasUri 
{ 
    public Uri GetUri(); 
} 

重構這個和你的層次結構實現此接口。比你可以使用

public Uri GetUri(object obj) 
{ 
    IHasUri hasUri = obj as IHasUri; 
    if(hasUri != null) 
     Uri uri = hasUri.GetUri(); 

    // bla bla bla 
} 
0

你可以有一個List<Type>()與你想要檢查的所有類型並迭代該列表。但我認爲這不會讓代碼更快。

+0

散列表會更好。 – leppie 2011-05-10 08:37:31

+0

我不想要「更快」的代碼,但「更具可讀性」的代碼:)。問題是,每種類型的處理代碼是不一樣的,所以我不認爲列表是合適的。開關是更合適的選擇 – Vimvq1987 2011-05-10 08:37:54

0

你不能switch-case類型。

開關表達或case標籤必須是一個布爾,焦炭,串,積分,enum或相應空類型

5

幾個選項:

  • 如果」重新使用C#4,您可以使用動態分類,並將方法分成多個過載:

    public Uri GetUri(dynamic obj) 
    { 
        return GetUriImpl(obj); 
    } 
    
    private Uri GetUriImpl(Entry entry) 
    { 
        ... 
    } 
    
    private Uri GetUriImpl(EntryComment comment) 
    { 
        ... 
    } 
    

    在這種情況下,如果它不是已知類型,您可能需要某種「backstop」方法。

  • 您可以創建一個Dictionary<Type, Func<object, Uri>>

    private static Dictionary<Type, Func<object, Uri>> UriProviders = 
        new Dictionary<Type, Func<object, Uri>> { 
        { typeof(Entry), value => ... }, 
        { typeof(EntryComment), value => ... }, 
        { typeof(Blog), value => ... }, 
    }; 
    

    然後:

    public Uri GetUri(object obj) 
    { 
        Func<object, Uri> provider; 
        if (!UriProviders.TryGetValue(obj.GetType(), out provider)) 
        { 
         // Handle unknown type case 
        } 
        return provider(obj); 
    } 
    

    注意這不會涵蓋您收到的Entry

  • 亞型的情況下

這些都不是特別好,請注意......我懷疑更高層次的重新設計可能更可取。

+0

+1,只有答案,實際顯示如何做到這一點,並沒有打破/封閉原則 – jgauffin 2011-05-10 08:40:05

1

我認爲Lasse五。卡爾森擁有的在他的評論的權利,重新設計是比較合適的也許

像Stecya表明

public interface IUriAccessible { //or some sort of a more descriptive name 
    Uri Url {get;} 
} 

,然後爲你關心的每個對象,例如Entry,你可以你可以創建一個接口

public class Entry:IUriAccessible { 
    //... other code here 
    public Uri Url { 
     get { 
      //return uri here 
     } 
    } 
} 

,現在你可以把它叫做對象

var entry = new Entry(); 
var uri = entry.Url;