如何在“可能”类型的对象之间切换?

时间:2011-05-10 08:32:55

标签: c# .net types switch-statement

  

可能重复:
  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可能的“可能”类型的技术。

我该如何重构这个?

谢谢。

5 个答案:

答案 0 :(得分:5)

有两种选择:

  • 如果您使用的是C#4,则可以使用动态类型,并将方法拆分为多个重载:

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

    在这种情况下,如果不是已知类型,您可能需要某种“逆止”方法。

  • 您可以创建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等子类型的情况。

这些都不是特别好,请注意......我怀疑更高级别的重新设计可能更合适。

答案 1 :(得分: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 
}

答案 2 :(得分:1)

我认为Lasse V. Karlsen在评论中有权利,重新设计也许更适合

您可以创建一个像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;

答案 3 :(得分:0)

您可以拥有一个List<Type>(),其中包含您要检查的所有类型并迭代该列表。但我认为这不会使代码更快。

答案 4 :(得分:0)

您不能switch-case种类型。

  

开关表达式或大小写标签必须是bool,char,string,integral,enum或相应的可空类型